Project

Profile

Help

How to connect?
Download (39.9 KB) Statistics
| Branch: | Tag: | Revision:

he / latest9.1 / bn / csource / api / Saxon.Api / Configuration.cs @ e090dcb1

1
using System;
2
using System.IO;
3
using System.Xml;
4
using System.Collections;
5
using System.Collections.Specialized;
6
using System.Reflection;
7
using System.Globalization;
8
using javax.xml.transform;
9
using javax.xml.transform.stream;
10
using JClass = java.lang.Class;
11
using JBoolean = java.lang.Boolean;
12
using JResult = javax.xml.transform.Result;
13
using JSource = javax.xml.transform.Source;
14
using JProperties = java.util.Properties;
15
using JConfiguration = net.sf.saxon.Configuration;
16
using JVersion = net.sf.saxon.Version;
17
using JDocumentWrapper = net.sf.saxon.dotnet.DocumentWrapper;
18
using JDotNetObjectModel = net.sf.saxon.dotnet.DotNetObjectModel;
19
using JNodeInfo = net.sf.saxon.om.NodeInfo;
20
using JDocumentInfo = net.sf.saxon.om.DocumentInfo;
21
using JSingletonNode = net.sf.saxon.value.SingletonNode;
22
using JValue = net.sf.saxon.value.Value;
23
using JValueRepresentation = net.sf.saxon.om.ValueRepresentation;
24
using JPipelineConfiguration = net.sf.saxon.@event.PipelineConfiguration;
25
using JXPathContext = net.sf.saxon.expr.XPathContext;
26
using JSequenceExtent = net.sf.saxon.value.SequenceExtent;
27
using AugmentedSource = net.sf.saxon.AugmentedSource;
28
using StructuredQName = net.sf.saxon.om.StructuredQName;
29
using Whitespace = net.sf.saxon.value.Whitespace;
30
using StaticQueryContext = net.sf.saxon.query.StaticQueryContext;
31
using JReceiver = net.sf.saxon.@event.Receiver;
32
using JTreeReceiver = net.sf.saxon.@event.TreeReceiver;
33
using JNamespaceReducer = net.sf.saxon.@event.NamespaceReducer;
34
using net.sf.saxon.om;
35
using net.sf.saxon.pull;
36
using net.sf.saxon.dotnet;
37

    
38

    
39
namespace Saxon.Api
40
{
41

    
42
    /// <summary>
43
    /// The Processor class serves three purposes: it allows global Saxon configuration
44
    /// options to be set; it acts as a factory for generating XQuery, XPath, and XSLT
45
    /// compilers; and it owns certain shared resources such as the Saxon NamePool and 
46
    /// compiled schemas. This is the first object that a Saxon application should create. Once
47
    /// established, a Processor may be used in multiple threads.
48
    /// </summary>
49

    
50
    [Serializable]
51
    public class Processor
52
    {
53

    
54
        //Transformation data variables
55
        internal JConfiguration config;
56
        private SchemaManager schemaManager = null;
57

    
58
        /// <summary>
59
        /// Create a new Processor
60
        /// </summary>
61

    
62
        public Processor()
63
        {
64
            config = new JConfiguration();
65
            config.setURIResolver(new DotNetURIResolver(new XmlUrlResolver()));
66
            config.setCollectionURIResolver(new DotNetCollectionURIResolver());
67
            config.registerExternalObjectModel(new DotNetObjectModelDefinition());
68
        }
69

    
70
        /// <summary>
71
        /// Create a Processor, indicating whether it is to be schema-aware.
72
        /// </summary>
73
        /// <param name="schemaAware">Set to true if the Processor is to be schema-aware.
74
        /// This requires the Saxon-SA product to be installed, with a valid license key.</param>
75

    
76
        public Processor(bool schemaAware) 
77
            // newline needed by documentation stylesheet
78
            : this(schemaAware, false) { }
79

    
80
        /// <summary>
81
        /// Create a Processor, indicating whether it is to be schema-aware.
82
        /// </summary>
83
        /// <param name="schemaAware">Set to true if the Processor is to be schema-aware.
84
        /// This requires the Saxon-SA product to be installed, with a valid license key.</param>
85
        /// <param name="loadLocally">This option has no effect at this release.</param>
86

    
87
        public Processor(bool schemaAware, bool loadLocally)
88
        {
89
            if (schemaAware)
90
            {
91
                //if (loadLocally) {
92
                //    Assembly asm = Assembly.Load("saxon8sa");
93
                //} else {
94
                //    try {
95
                //        int[] v = JVersion.getStructuredVersionNumber();
96
                //        AssemblyName asn = new AssemblyName();
97
                //        asn.Name = "saxon8sa";
98
                //        asn.Version = new Version(v[0], v[1], v[2], v[3]);
99
                //        //asn.Version = new Version(JVersion.getMajorVersion(), JVersion.getMinorVersion());
100
                //        asn.SetPublicKeyToken(new byte[] { 0xe1, 0xfd, 0xd0, 0x02, 0xd5, 0x08, 0x3f, 0xe6 });
101
                //        asn.CultureInfo = new CultureInfo("");
102
                //        Assembly asm = Assembly.Load(asn);
103
                //        // try to load the saxon8sa.dll assembly
104
                //        //Assembly asm = Assembly.Load("saxon8sa, Ver=" + JVersion.getProductVersion() + ".0.1, " +
105
                //        //    @"SN=e1fdd002d5083fe6, Loc=neutral");
106
                //    } catch (Exception e) {
107
                //        Console.WriteLine("Cannot load Saxon-SA software (assembly saxon8sa.dll version " +
108
                //            JVersion.getProductVersion() + ".0.1)");
109
                //        throw e;
110
                //    }
111
                //}
112
                config = JConfiguration.makeSchemaAwareConfiguration(null,
113
                    DotNetPlatform.getSaxonSaFullyQualifiedClassName());
114
                //config = new com.saxonica.validate.SchemaAwareConfiguration();
115
                schemaManager = new SchemaManager(config);
116
            }
117
            else
118
            {
119
                config = new JConfiguration();
120
            }
121
            config.setURIResolver(new DotNetURIResolver(new XmlUrlResolver()));
122
            config.setCollectionURIResolver(new DotNetCollectionURIResolver());
123
        }
124

    
125
        /// <summary>
126
        /// Get the full name of the Saxon product version implemented by this Processor
127
        /// </summary>
128

    
129
        public string ProductTitle
130
        {
131
            get { return JVersion.getProductTitle(); }
132
        }
133

    
134
        /// <summary>
135
        /// Get the Saxon product version number (for example, "8.8.1")
136
        /// </summary>
137

    
138
        public string ProductVersion
139
        {
140
            get { return JVersion.getProductVersion(); }
141
        }
142

    
143

    
144
        /// <summary>
145
        /// Indicates whether the Processor is schema-aware
146
        /// </summary>
147

    
148
        public bool IsSchemaAware
149
        {
150
            get { return config.isSchemaAware(JConfiguration.XML_SCHEMA); }
151
        }
152

    
153
        /// <summary>
154
        /// Gets the SchemaManager for the Processor. Returns null
155
        /// if the Processor is not schema-aware.
156
        /// </summary>
157

    
158
        public SchemaManager SchemaManager
159
        {
160
            get { return schemaManager; }
161
        }
162

    
163
        /// <summary>
164
        /// An XmlResolver, which will be used while compiling and running queries, 
165
        /// XPath expressions, and stylesheets, if no other XmlResolver is nominated
166
        /// </summary>
167
        /// <remarks>
168
        /// <para>By default an <c>XmlUrlResolver</c> is used. This means that the responsibility
169
        /// for resolving and dereferencing URIs rests with the .NET platform, not with the
170
        /// GNU Classpath.</para>
171
        /// <para>When Saxon invokes a user-written <c>XmlResolver</c>, the <c>GetEntity</c> method
172
        /// may return any of: a <c>System.IO.Stream</c>; a <c>System.IO.TextReader</c>; or a
173
        /// <c>java.xml.transform.Source</c>.</para>
174
        /// </remarks>
175

    
176
        public XmlResolver XmlResolver
177
        {
178
            get
179
            {
180
                return ((DotNetURIResolver)config.getURIResolver()).getXmlResolver();
181
            }
182
            set
183
            {
184
                config.setURIResolver(new DotNetURIResolver(value));
185
            }
186
        }
187

    
188
        /// <summary>
189
        /// Create a new <c>DocumentBuilder</c>, which may be used to build XDM documents from
190
        /// a variety of sources.
191
        /// </summary>
192
        /// <returns>A new <c>DocumentBuilder</c></returns>
193

    
194
        public DocumentBuilder NewDocumentBuilder()
195
        {
196
            DocumentBuilder builder = new DocumentBuilder(this);
197
            builder.XmlResolver = XmlResolver;
198
            return builder;
199
        }
200

    
201
        /// <summary>
202
        /// Create a new XQueryCompiler, which may be used to compile XQuery queries.
203
        /// </summary>
204
        /// <remarks>
205
        /// The returned XQueryCompiler retains a live link to the Processor, and
206
        /// may be affected by subsequent changes to the Processor.
207
        /// </remarks>
208
        /// <returns>A new XQueryCompiler</returns>
209

    
210
        public XQueryCompiler NewXQueryCompiler()
211
        {
212
            return new XQueryCompiler(this);
213
        }
214

    
215
        /// <summary>
216
        /// Create a new XsltCompiler, which may be used to compile XSLT stylesheets.
217
        /// </summary>
218
        /// <remarks>
219
        /// The returned XsltCompiler retains a live link to the Processor, and
220
        /// may be affected by subsequent changes to the Processor.
221
        /// </remarks>
222
        /// <returns>A new XsltCompiler</returns>
223

    
224
        public XsltCompiler NewXsltCompiler()
225
        {
226
            return new XsltCompiler(config);
227
        }
228

    
229
        /// <summary>
230
        /// Create a new XPathCompiler, which may be used to compile XPath expressions.
231
        /// </summary>
232
        /// <remarks>
233
        /// The returned XPathCompiler retains a live link to the Processor, and
234
        /// may be affected by subsequent changes to the Processor.
235
        /// </remarks>
236
        /// <returns>A new XPathCompiler</returns>
237

    
238
        public XPathCompiler NewXPathCompiler()
239
        {
240
            return new XPathCompiler(config);
241
        }
242

    
243
        /// <summary>
244
        /// The XML version used in this <c>Processor</c> (for example, this determines what characters
245
        /// are permitted in a name)
246
        /// </summary>
247
        /// <remarks>
248
        /// The value must be 1.0 or 1.1, as a <c>decimal</c>. The default version is currently 1.0, but may
249
        /// change in the future.
250
        /// </remarks>
251

    
252
        public decimal XmlVersion
253
        {
254
            get
255
            {
256
                return (config.getXMLVersion() == JConfiguration.XML10 ? 1.0m : 1.1m);
257
            }
258
            set
259
            {
260
                if (value == 1.0m)
261
                {
262
                    config.setXMLVersion(JConfiguration.XML10);
263
                }
264
                else if (value == 1.1m)
265
                {
266
                    config.setXMLVersion(JConfiguration.XML11);
267
                }
268
                else
269
                {
270
                    throw new ArgumentException("Invalid XML version: " + value);
271
                }
272
            }
273
        }
274

    
275
        /// <summary>
276
        /// Register a named collection. A collection is identified by a URI (the collection URI),
277
        /// and its content is represented by an <c>IEnumerable</c> that enumerates the contents
278
        /// of the collection. The values delivered by this enumeration are Uri values, which 
279
        /// can be mapped to nodes using the registered <c>XmlResolver</c>.
280
        /// </summary>
281
        /// <param name="collectionUri">The URI used to identify the collection in a call
282
        /// of the XPath <c>collection()</c> function. The default collection is registered
283
        /// by supplying null as the value of this argument (this is the collection returned
284
        /// when the XPath <c>collection()</c> function is called with no arguments).</param> 
285
        /// <param name="contents">An enumerable object that represents the contents of the
286
        /// collection, as a sequence of document URIs. The enumerator returned by this
287
        /// IEnumerable object must return instances of the Uri class.</param>
288
        /// <remarks>
289
        /// <para>Collections should be stable: that is, two calls to retrieve the same collection URI
290
        /// should return the same sequence of document URIs. This requirement is imposed by the
291
        /// W3C specifications, but in the case of a user-defined collection it is not enforced by
292
        /// the Saxon product.</para>
293
        /// <para>A collection may be "unregistered" by providing null as the value of the
294
        /// contents argument. A collection may be replaced by specifying the URI of an existing
295
        /// collection.</para>
296
        /// <para>Collections registered with a processor are available to all queries and stylesheets
297
        /// running under the control that processor. Collections should not normally be registered
298
        /// while queries and transformations are in progress.</para>
299
        /// </remarks>
300
        /// 
301

    
302
        public void RegisterCollection(Uri collectionUri, IEnumerable contents)
303
        {
304
            String u = (collectionUri == null ? null : collectionUri.ToString());
305
            DotNetCollectionURIResolver resolver =
306
                (DotNetCollectionURIResolver)config.getCollectionURIResolver();
307
            resolver.registerCollection(u, contents);
308
        }
309

    
310
        /// <summary>
311
        /// Copy an XdmValue to an XmlDestination
312
        /// </summary>
313
        /// <remarks>
314
        /// This method can be used to copy any kind of <c>XdmValue</c> to any kind
315
        /// of <c>XdmDestination</c>. The supplied <c>XdmValue</c> is first converted
316
        /// to an XML document according to the rules of the XSLT/XQuery serialization
317
        /// specification (for example, if the <c>XdmValue</c> is a sequence of atomic
318
        /// values, they will be turned in a text node in which the values are converted
319
        /// to strings and separated by single spaces). The resulting document is then
320
        /// written to the supplied <c>XmlDestination</c>.</remarks>
321
        /// <param name="sequence">The value to be written</param>
322
        /// <param name="destination">The destination to which the value should be written</param>
323
        /// 
324

    
325
        public void WriteXdmValue(XdmValue sequence, XmlDestination destination)
326
        {
327
            JResult result = destination.GetResult();
328
            JReceiver r = config.getSerializerFactory().getReceiver(result,
329
                config.makePipelineConfiguration(), new JProperties());
330
            r = new JNamespaceReducer(r);
331
            JTreeReceiver tree = new JTreeReceiver(r);
332
            tree.open();
333
            tree.startDocument(0);
334
            foreach (XdmItem it in sequence)
335
            {
336
                tree.append((Item)it.Unwrap(), 0, JNodeInfo.__Fields.ALL_NAMESPACES);
337
            }
338
            tree.endDocument();
339
            tree.close();
340
        }
341

    
342

    
343
        /// <summary>
344
        /// The underlying Configuration object in the Saxon implementation
345
        /// </summary>
346
        /// <remarks>
347
        /// <para>This property provides access to internal methods in the Saxon engine that are
348
        /// not specifically exposed in the .NET API. In general these methods should be
349
        /// considered to be less stable than the classes in the Saxon.Api namespace.</para> 
350
        /// <para>The internal methods follow
351
        /// Java naming conventions rather than .NET conventions.</para>
352
        /// <para>Information about the returned object (and the objects it provides access to)
353
        /// is included in the Saxon JavaDoc docmentation, available 
354
        /// <link href="http://www.saxonica.com/documentation/javadoc/index.html">online</link>.
355
        /// </para>
356
        /// </remarks>
357

    
358
        public net.sf.saxon.Configuration Implementation
359
        {
360
            get { return config; }
361
        }
362

    
363
        /// <summary>
364
        /// Set a configuration property
365
        /// </summary>
366
        /// <remarks>
367
        /// <para>This method provides the ability to set named properties of the configuration.
368
        /// The property names are set as strings, whose values can be found in the Java
369
        /// class <c>net.sf.saxon.FeatureKeys</c>. The property values are always strings. 
370
        /// Properties whose values are other types are not available via this interface:
371
        /// however all properties have an effective equivalent whose value is a string.
372
        /// Note that on/off properties are set using the strings "true" and "false".</para>
373
        /// <para><i>Method added in Saxon 9.1</i></para>
374
        /// </remarks>
375
        /// <param name="name">The property name</param>
376
        /// <param name="value">The property value</param>
377

    
378
        public void SetProperty(String name, String value)
379
        {
380
            config.setConfigurationProperty(name, value);
381
        }
382

    
383
        /// <summary>
384
        /// Get the value of a configuration property
385
        /// </summary>
386
        /// <remarks>
387
        /// <para>This method provides the ability to get named properties of the configuration.
388
        /// The property names are supplied as strings, whose values can be found in the Java
389
        /// class <c>net.sf.saxon.FeatureKeys</c>. The property values are always returned as strings. 
390
        /// Properties whose values are other types are returned by converting the value to a string.
391
        /// Note that on/off properties are returned using the strings "true" and "false".</para>
392
        /// <para><i>Method added in Saxon 9.1</i></para>
393
        /// </remarks>
394
        /// <param name="name">The property name</param>
395
        /// <returns>The property value, as a string; or null if the property is unset.</returns>
396

    
397
        public String GetProperty(String name)
398
        {
399
            Object obj = config.getConfigurationProperty(name);
400
            return (obj == null ? null : obj.ToString());
401
        }
402

    
403
    }
404

    
405
    /// <summary>
406
    /// The <c>DocumentBuilder</c> class enables XDM documents to be built from various sources.
407
    /// The class is always instantiated using the <c>NewDocumentBuilder</c> method
408
    /// on the <c>Processor</c> object.
409
    /// </summary>
410

    
411
    [Serializable]
412
    public class DocumentBuilder
413
    {
414

    
415
        private Processor processor;
416
        private JConfiguration config;
417
        private XmlResolver xmlResolver;
418
        private SchemaValidationMode validation;
419
        private bool dtdValidation;
420
        private bool lineNumbering;
421
        private WhitespacePolicy whitespacePolicy;
422
        private Uri baseUri;
423
        private QName topLevelElement;
424
        private TreeModel treeModel = TreeModel.Unspecified;
425

    
426
        internal DocumentBuilder(Processor processor)
427
        {
428
            this.processor = processor;
429
            this.config = processor.Implementation;
430
        }
431

    
432
        /// <summary>
433
        /// An XmlResolver, which will be used to resolve URIs of documents being loaded
434
        /// and of references to external entities within those documents (including any external DTD).
435
        /// </summary>
436
        /// <remarks>
437
        /// <para>By default an <c>XmlUrlResolver</c> is used. This means that the responsibility
438
        /// for resolving and dereferencing URIs rests with the .NET platform (and not with the
439
        /// GNU Classpath).</para>
440
        /// <para>When Saxon invokes a user-written <c>XmlResolver</c>, the <c>GetEntity</c> method
441
        /// may return any of: a <c>System.IO.Stream</c>; a <c>System.IO.TextReader</c>; or a
442
        /// <c>java.xml.transform.Source</c>. However, if the <c>XmlResolver</c> is called
443
        /// by the XML parser to resolve external entity references, then it must return an 
444
        /// instance of <c>System.IO.Stream</c>.</para>
445
        /// </remarks>
446

    
447
        public XmlResolver XmlResolver
448
        {
449
            get
450
            {
451
                return xmlResolver;
452
            }
453
            set
454
            {
455
                xmlResolver = value;
456
            }
457
        }
458

    
459
        /// <summary>
460
        /// Determines whether line numbering is enabled for documents loaded using this
461
        /// <c>DocumentBuilder</c>.
462
        /// </summary>
463
        /// <remarks>
464
        /// <para>By default, line numbering is disabled.</para>
465
        /// <para>Line numbering is not available for all kinds of source: in particular,
466
        /// it is not available when loading from an existing XmlDocument.</para>
467
        /// <para>The resulting line numbers are accessible to applications using the
468
        /// extension function saxon:line-number() applied to a node.</para>  
469
        /// <para>Line numbers are maintained only for element nodes; the line number
470
        /// returned for any other node will be that of the most recent element.</para> 
471
        /// </remarks>
472

    
473
        public bool IsLineNumbering
474
        {
475
            get
476
            {
477
                return lineNumbering;
478
            }
479
            set
480
            {
481
                lineNumbering = value;
482
            }
483
        }
484

    
485
        /// <summary>
486
        /// Determines whether schema validation is applied to documents loaded using this
487
        /// <c>DocumentBuilder</c>, and if so, whether it is strict or lax.
488
        /// </summary>
489
        /// <remarks>
490
        /// <para>By default, no schema validation takes place.</para>
491
        /// <para>This option requires the schema-aware version of the Saxon product (Saxon-SA).</para>
492
        /// </remarks>
493

    
494
        public SchemaValidationMode SchemaValidationMode
495
        {
496
            get
497
            {
498
                return validation;
499
            }
500
            set
501
            {
502
                validation = value;
503
            }
504
        }
505

    
506
        /// <summary>
507
        /// The required name of the top level element in a document instance being validated
508
        /// against a schema.
509
        /// </summary>
510
        /// <remarks>
511
        /// <para>If this property is set, and if schema validation is requested, then validation will
512
        /// fail unless the outermost element of the document has the required name.</para>
513
        /// <para>This option requires the schema-aware version of the Saxon product (Saxon-SA).</para>
514
        /// </remarks> 
515

    
516
        public QName TopLevelElementName
517
        {
518
            get
519
            {
520
                return topLevelElement;
521
            }
522
            set
523
            {
524
                topLevelElement = value;
525
            }
526
        }
527

    
528
        /// <summary>
529
        /// Determines whether DTD validation is applied to documents loaded using this
530
        /// <c>DocumentBuilder</c>.
531
        /// </summary>
532
        /// <remarks>
533
        ///
534
        /// <para>By default, no DTD validation takes place.</para>
535
        /// 
536
        /// </remarks>
537

    
538
        public bool DtdValidation
539
        {
540
            get
541
            {
542
                return dtdValidation;
543
            }
544
            set
545
            {
546
                dtdValidation = value;
547
            }
548
        }
549

    
550
        /// <summary>
551
        /// Determines the whitespace stripping policy applied when loading a document
552
        /// using this <c>DocumentBuilder</c>.
553
        /// </summary>
554
        /// <remarks>
555
        /// <para>By default, whitespace text nodes appearing in element-only content
556
        /// are stripped, and all other whitespace text nodes are retained.</para>
557
        /// </remarks>
558

    
559
        public WhitespacePolicy WhitespacePolicy
560
        {
561
            get
562
            {
563
                return whitespacePolicy;
564
            }
565
            set
566
            {
567
                whitespacePolicy = value;
568
            }
569
        }
570

    
571
        ///<summary>
572
        /// The Tree Model implementation to be used for the constructed document. By default
573
        /// the TinyTree is used. The main reason for using the LinkedTree alternative is if
574
        /// updating is required (the TinyTree is not updateable)
575
        ///</summary>
576

    
577
        public TreeModel TreeModel
578
        {
579
            get
580
            {
581
                return treeModel;
582
            }
583
            set
584
            {
585
                treeModel = value;
586
            }
587
        }
588

    
589
        /// <summary>
590
        /// The base URI of a document loaded using this <c>DocumentBuilder</c>.
591
        /// This is used for resolving any relative URIs appearing
592
        /// within the document, for example in references to DTDs and external entities.
593
        /// </summary>
594
        /// <remarks>
595
        /// This information is required when the document is loaded from a source that does not
596
        /// provide an intrinsic URI, notably when loading from a Stream or a TextReader.
597
        /// </remarks>
598

    
599

    
600
        public Uri BaseUri
601
        {
602
            get { return baseUri; }
603
            set { baseUri = value; }
604
        }
605

    
606
        /// <summary>
607
        /// Load an XML document, retrieving it via a URI.
608
        /// </summary>
609
        /// <remarks>
610
        /// <para>Note that the type <c>Uri</c> requires an absolute URI.</para>
611
        /// <para>The URI is dereferenced using the registered <c>XmlResolver</c>.</para>
612
        /// <para>This method takes no account of any fragment part in the URI.</para>
613
        /// <para>The <c>role</c> passed to the <c>GetEntity</c> method of the <c>XmlResolver</c> 
614
        /// is "application/xml", and the required return type is <c>System.IO.Stream</c>.</para>
615
        /// <para>The document located via the URI is parsed using the <c>System.Xml</c> parser.</para>
616
        /// <para>Note that the Microsoft <c>System.Xml</c> parser does not report whether attributes are
617
        /// defined in the DTD as being of type <c>ID</c> and <c>IDREF</c>. This is true whether or not
618
        /// DTD-based validation is enabled. This means that such attributes are not accessible to the 
619
        /// <c>id()</c> and <c>idref()</c> functions.</para>
620
        /// </remarks>
621
        /// <param name="uri">The URI identifying the location where the document can be
622
        /// found. This will also be used as the base URI of the document (regardless
623
        /// of the setting of the <c>BaseUri</c> property).</param>
624
        /// <returns>An <c>XdmNode</c>. This will be
625
        ///  the document node at the root of the tree of the resulting in-memory document. 
626
        /// </returns>
627

    
628
        public XdmNode Build(Uri uri)
629
        {
630
            Object obj = XmlResolver.GetEntity(uri, "application/xml", Type.GetType("System.IO.Stream"));
631
            if (obj is Stream)
632
            {
633
                try
634
                {
635
                    return Build((Stream)obj, uri);
636
                }
637
                finally
638
                {
639
                    ((Stream)obj).Close();
640
                }
641
            }
642
            else
643
            {
644
                throw new ArgumentException("Invalid type of result from XmlResolver.GetEntity: " + obj);
645
            }
646
        }
647

    
648
        /// <summary>
649
        /// Load an XML document supplied as raw (lexical) XML on a Stream.
650
        /// </summary>
651
        /// <remarks>
652
        /// <para>The document is parsed using the <c>System.Xml</c> parser.</para>
653
        /// <para>Before calling this method, the BaseUri property must be set to identify the
654
        /// base URI of this document, used for resolving any relative URIs contained within it.</para>
655
        /// <para>Note that the Microsoft <c>System.Xml</c> parser does not report whether attributes are
656
        /// defined in the DTD as being of type <c>ID</c> and <c>IDREF</c>. This is true whether or not
657
        /// DTD-based validation is enabled. This means that such attributes are not accessible to the 
658
        /// <c>id()</c> and <c>idref()</c> functions.</para>         
659
        /// </remarks>
660
        /// <param name="input">The Stream containing the XML source to be parsed</param>
661
        /// <returns>An <c>XdmNode</c>, the document node at the root of the tree of the resulting
662
        /// in-memory document
663
        /// </returns>
664

    
665
        public XdmNode Build(Stream input)
666
        {
667
            if (baseUri == null)
668
            {
669
                throw new ArgumentException("No base URI supplied");
670
            }
671
            return Build(input, baseUri);
672
        }
673

    
674
        // Build a document from a given stream, with the base URI supplied
675
        // as an extra argument
676

    
677
        internal XdmNode Build(Stream input, Uri baseUri)
678
        {
679
            Source source;
680
            if (processor.GetProperty("http://saxon.sf.net/feature/preferJaxpParser") == "true")
681
            {
682
                source = new StreamSource(new DotNetInputStream(input), baseUri.ToString());
683
            }
684
            else
685
            {
686

    
687
                XmlReader parser = new XmlTextReader(baseUri.ToString(), input);
688
                ((XmlTextReader)parser).Normalization = true;
689
                switch (whitespacePolicy)
690
                {
691
                    case WhitespacePolicy.PreserveAll:
692
                        ((XmlTextReader)parser).WhitespaceHandling = WhitespaceHandling.All;
693
                        break;
694
                    case WhitespacePolicy.StripAll:
695
                        ((XmlTextReader)parser).WhitespaceHandling = WhitespaceHandling.None;
696
                        break;
697
                    case WhitespacePolicy.StripIgnorable:
698
                        ((XmlTextReader)parser).WhitespaceHandling = WhitespaceHandling.Significant;
699
                        break;
700
                }
701
                if (xmlResolver != null)
702
                {
703
                    ((XmlTextReader)parser).XmlResolver = xmlResolver;
704
                }
705
                // Always need a validating parser, because that's the only way to get entity references expanded
706
                parser = new XmlValidatingReader(parser);
707
                if (dtdValidation)
708
                {
709
                    ((XmlValidatingReader)parser).ValidationType = ValidationType.DTD;
710
                }
711
                else
712
                {
713
                    ((XmlValidatingReader)parser).ValidationType = ValidationType.None;
714
                }
715
                source = new PullSource(new DotNetPullProvider(parser));
716
                source.setSystemId(baseUri.ToString());
717
            }
718
            source = augmentSource(source);
719
            DocumentInfo doc = config.buildDocument(source);
720
            return (XdmNode)XdmValue.Wrap(doc);
721
        }
722

    
723
        private Source augmentSource(Source source)
724
        {
725
            if (validation != SchemaValidationMode.None)
726
            {
727
                source = AugmentedSource.makeAugmentedSource(source);
728
                if (validation == SchemaValidationMode.Strict)
729
                {
730
                    ((AugmentedSource)source).setSchemaValidationMode(Validation.STRICT);
731
                }
732
                else
733
                {
734
                    ((AugmentedSource)source).setSchemaValidationMode(Validation.LAX);
735
                }
736
            }
737
            if (topLevelElement != null)
738
            {
739
                source = AugmentedSource.makeAugmentedSource(source);
740
                ((AugmentedSource)source).setTopLevelElement(
741
                    new StructuredQName(
742
                        topLevelElement.Prefix, topLevelElement.Uri, topLevelElement.LocalName));
743
            }
744

    
745
            if (whitespacePolicy != WhitespacePolicy.PreserveAll)
746
            {
747
                source = AugmentedSource.makeAugmentedSource(source);
748
                if (whitespacePolicy == WhitespacePolicy.StripIgnorable)
749
                {
750
                    ((AugmentedSource)source).setStripSpace(Whitespace.IGNORABLE);
751
                }
752
                else
753
                {
754
                    ((AugmentedSource)source).setStripSpace(Whitespace.ALL);
755
                }
756
            }
757
            if (treeModel != TreeModel.Unspecified)
758
            {
759
                source = AugmentedSource.makeAugmentedSource(source);
760
                if (treeModel == TreeModel.TinyTree)
761
                {
762
                    ((AugmentedSource)source).setTreeModel(net.sf.saxon.@event.Builder.TINY_TREE);
763
                }
764
                else
765
                {
766
                    ((AugmentedSource)source).setTreeModel(net.sf.saxon.@event.Builder.LINKED_TREE);
767
                }
768
            }
769
            if (lineNumbering)
770
            {
771
                source = AugmentedSource.makeAugmentedSource(source);
772
                ((AugmentedSource)source).setLineNumbering(true);
773
            }
774
            if (dtdValidation)
775
            {
776
                source = AugmentedSource.makeAugmentedSource(source);
777
                ((AugmentedSource)source).setDTDValidationMode(Validation.STRICT);
778
            }
779
            return source;
780
        }
781

    
782
        /// <summary>
783
        /// Load an XML document, delivered using an XmlReader.
784
        /// </summary>
785
        /// <remarks>
786
        /// <para>The XmlReader is responsible for parsing the document; this method builds a tree
787
        /// representation of the document (in an internal Saxon format) and returns its document node.
788
        /// The XmlReader is not required to perform validation but it must expand any entity references.
789
        /// Saxon uses the properties of the <c>XmlReader</c> as supplied.</para>
790
        /// <para>Use of a plain <c>XmlTextReader</c> is discouraged, because it does not expand entity
791
        /// references. This should only be used if you know in advance that the document will contain
792
        /// no entity references (or perhaps if your query or stylesheet is not interested in the content
793
        /// of text and attribute nodes). Instead, with .NET 1.1 use an <c>XmlValidatingReader</c> (with <c>ValidationType</c>
794
        /// set to <c>None</c>). The constructor for <c>XmlValidatingReader</c> is obsolete in .NET 2.0,
795
        /// but the same effect can be achieved by using the <c>Create</c> method of <c>XmlReader</c> with
796
        /// appropriate <c>XmlReaderSettings</c></para>
797
        /// <para>Conformance with the W3C specifications requires that the <c>Normalization</c> property
798
        /// of an <c>XmlTextReader</c> should be set to <c>true</c>. However, Saxon does not insist
799
        /// on this.</para>
800
        /// <para>If the <c>XmlReader</c> performs schema validation, Saxon will ignore any resulting type
801
        /// information. Type information can only be obtained by using Saxon's own schema validator, which
802
        /// will be run if the <c>SchemaValidationMode</c> property is set to <c>Strict</c> or <c>Lax</c></para>
803
        /// <para>Note that the Microsoft <c>System.Xml</c> parser does not report whether attributes are
804
        /// defined in the DTD as being of type <c>ID</c> and <c>IDREF</c>. This is true whether or not
805
        /// DTD-based validation is enabled. This means that such attributes are not accessible to the 
806
        /// <c>id()</c> and <c>idref()</c> functions.</para>
807
        /// <para>Note that setting the <c>XmlResolver</c> property of the <c>DocumentBuilder</c>
808
        /// has no effect when this method is used; if an <c>XmlResolver</c> is required, it must
809
        /// be set on the <c>XmlReader</c> itself.</para>
810
        /// </remarks>
811
        /// <param name="reader">The XMLReader that supplies the parsed XML source</param>
812
        /// <returns>An <c>XdmNode</c>, the document node at the root of the tree of the resulting
813
        /// in-memory document
814
        /// </returns>
815

    
816
        public XdmNode Build(XmlReader reader)
817
        {
818
            PullProvider pp = new DotNetPullProvider(reader);
819
            pp.setPipelineConfiguration(config.makePipelineConfiguration());
820
            // pp = new PullTracer(pp);  /* diagnostics */
821
            Source source = new PullSource(pp);
822
            source.setSystemId(reader.BaseURI);
823
            source = augmentSource(source);
824
            DocumentInfo doc = config.buildDocument(source);
825
            return (XdmNode)XdmValue.Wrap(doc);
826
        }
827

    
828
        /// <summary>
829
        /// Load an XML DOM document, supplied as an <c>XmlNode</c>, into a Saxon XdmNode.
830
        /// </summary>
831
        /// <remarks>
832
        /// <para>
833
        /// The returned document will contain only the subtree rooted at the supplied node.
834
        /// </para>
835
        /// <para>
836
        /// This method copies the DOM tree to create a Saxon tree. See the <c>Wrap</c> method for
837
        /// an alternative that creates a wrapper the DOM tree, allowing it to be modified in situ.
838
        /// </para>
839
        /// </remarks>
840
        /// <param name="source">The DOM Node to be copied to form a Saxon tree</param>
841
        /// <returns>An <c>XdmNode</c>, the document node at the root of the tree of the resulting
842
        /// in-memory document
843
        /// </returns>
844

    
845
        public XdmNode Build(XmlNode source)
846
        {
847
            return Build(new XmlNodeReader(source));
848
        }
849

    
850
        /// <summary>
851
        /// Wrap an XML DOM document, supplied as an <c>XmlNode</c>, as a Saxon XdmNode.
852
        /// </summary>
853
        /// <remarks>
854
        /// <para>
855
        /// This method must be applied at the level of the Document Node. Unlike the
856
        /// <c>Build</c> method, the original DOM is not copied. This saves memory and
857
        /// time, but it also means that it is not possible to perform operations such as
858
        /// whitespace stripping and schema validation.
859
        /// </para>
860
        /// </remarks>
861
        /// <param name="doc">The DOM document node to be wrapped</param>
862
        /// <returns>An <c>XdmNode</c>, the Saxon document node at the root of the tree of the resulting
863
        /// in-memory document
864
        /// </returns>
865

    
866
        public XdmNode Wrap(XmlDocument doc)
867
        {
868
            String baseu = (baseUri == null ? null : baseUri.ToString());
869
            JDocumentWrapper wrapper = new JDocumentWrapper(doc, baseu, config);
870
            return (XdmNode)XdmValue.Wrap(wrapper);
871
        }
872

    
873

    
874
    }
875

    
876

    
877
    /// <summary>
878
    /// Enumeration identifying the various Schema validation modes
879
    /// </summary>
880

    
881
    public enum SchemaValidationMode
882
    {
883
        /// <summary>No validation</summary> 
884
        None,
885
        /// <summary>Strict validation</summary>
886
        Strict,
887
        /// <summary>Lax validation</summary>
888
        Lax
889
    }
890

    
891
    /// <summary>
892
    /// Enumeration identifying the various Whitespace stripping policies
893
    /// </summary>
894

    
895
    public enum WhitespacePolicy
896
    {
897
        /// <summary>No whitespace is stripped</summary> 
898
        PreserveAll,
899
        /// <summary>Whitespace text nodes appearing in element-only content are stripped</summary>
900
        StripIgnorable,
901
        /// <summary>All whitespace text nodes are stripped</summary>
902
        StripAll
903
    }
904

    
905
    /// <summary>
906
    /// Enumeration identifying the different tree model implementations
907
    /// </summary>
908
    /// 
909
    public enum TreeModel
910
    {
911
        /// <summary>
912
        /// Saxon TinyTree
913
        /// </summary>
914
        TinyTree,
915
        /// <summary>
916
        /// Saxon LinkedTree
917
        /// </summary>
918
        LinkedTree,
919
        /// <summary>
920
        /// Unspecified tree model
921
        /// </summary>
922
        Unspecified
923
    }
924

    
925
    internal class DotNetObjectModelDefinition : JDotNetObjectModel
926
    {
927

    
928
        public override bool isXdmValue(object obj)
929
        {
930
            return obj is XdmValue;
931
        }
932

    
933
        public override bool isXdmValueType(Type type)
934
        {
935
            return typeof(XdmValue).IsAssignableFrom(type);
936
        }
937

    
938
        public override JValueRepresentation unwrapXdmValue(object obj)
939
        {
940
            return ((XdmValue)obj).Unwrap();
941
        }
942

    
943
        public override object wrapAsXdmValue(JValue value)
944
        {
945
            return XdmValue.Wrap(value);
946
        }
947

    
948
        public override bool isXmlNodeType(Type type)
949
        {
950
            return typeof(System.Xml.XmlNode).IsAssignableFrom(type);
951
        }
952

    
953
    }
954

    
955
}
956

    
957
//
958
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
959
// you may not use this file except in compliance with the License. You may obtain a copy of the
960
// License at http://www.mozilla.org/MPL/
961
//
962
// Software distributed under the License is distributed on an "AS IS" basis,
963
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
964
// See the License for the specific language governing rights and limitations under the License.
965
//
966
// The Original Code is: all this file.
967
//
968
// The Initial Developer of the Original Code is Michael H. Kay.
969
//
970
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
971
//
972
// Contributor(s): none.
973
//
(1-1/8)