Project

Profile

Help

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

he / latest9.3 / hen / csource / api / Saxon.Api / Configuration.cs @ 78a5bde2

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 JBufferedReader = java.io.BufferedReader;
16
using JStringReader = java.io.StringReader;
17
using JConfiguration = net.sf.saxon.Configuration;
18
using JVersion = net.sf.saxon.Version;
19
using JDocumentWrapper = net.sf.saxon.dotnet.DocumentWrapper;
20
using JDotNetObjectModel = net.sf.saxon.dotnet.DotNetObjectModel;
21
using JNodeInfo = net.sf.saxon.om.NodeInfo;
22
using JDocumentInfo = net.sf.saxon.om.DocumentInfo;
23
//using JSingletonItem = net.sf.saxon.value.SingletonItem;
24
using JValue = net.sf.saxon.value.Value;
25
using JValueRepresentation = net.sf.saxon.om.ValueRepresentation;
26
using JPipelineConfiguration = net.sf.saxon.@event.PipelineConfiguration;
27
using JXPathContext = net.sf.saxon.expr.XPathContext;
28
using JSequenceExtent = net.sf.saxon.value.SequenceExtent;
29
using AugmentedSource = net.sf.saxon.lib.AugmentedSource;
30
using StructuredQName = net.sf.saxon.om.StructuredQName;
31
using Whitespace = net.sf.saxon.value.Whitespace;
32
using StaticQueryContext = net.sf.saxon.query.StaticQueryContext;
33
using JReceiver = net.sf.saxon.@event.Receiver;
34
using JTreeReceiver = net.sf.saxon.@event.TreeReceiver;
35
using JNamespaceReducer = net.sf.saxon.@event.NamespaceReducer;
36
using JValidation = net.sf.saxon.lib.Validation;
37
using net.sf.saxon.om;
38
using net.sf.saxon.pull;
39
using net.sf.saxon.dotnet;
40

    
41

    
42
namespace Saxon.Api
43
{
44

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

    
53
    [Serializable]
54
    public class Processor
55
    {
56

    
57
        //Transformation data variables
58
        internal JConfiguration config;
59
        private SchemaManager schemaManager = null;
60

    
61
        /// <summary>
62
        /// Create a new Processor. This Processor will have capabilities that depend on the version
63
        /// of the software that has been loaded, and on the features that have been licensed.
64
        /// </summary>
65

    
66
        public Processor()
67
        {
68
            config = JConfiguration.newConfiguration();
69
            config.registerExternalObjectModel(new DotNetObjectModelDefinition());
70
            config.setProcessor(this);
71
        }
72

    
73
        /// <summary>
74
        /// Create a Processor.
75
        /// </summary>
76
        /// <param name="licensedEdition">Set to true if the Processor is to use a licensed edition of Saxon
77
        /// (that is, Saxon-PE or Saxon-EE). If true, the Processor will attempt to enable the capabilities
78
        /// of the licensed edition of Saxon, according to the version of the software that is loaded, and will
79
        /// verify the license key. If false, the Processor will load a default Configuration that gives restricted
80
        /// capability and does not require a license, regardless of which version of the software is actually being run.</param>
81

    
82
        public Processor(bool licensedEdition) 
83
            // newline needed by documentation stylesheet
84
            : this(licensedEdition, false) { }
85

    
86
        /// <summary>
87
        /// Create a Processor.
88
        /// </summary>
89
        /// <param name="licensedEdition">Set to true if the Processor is to use a licensed edition of Saxon
90
        /// (that is, Saxon-PE or Saxon-EE). If true, the Processor will attempt to enable the capabilities
91
        /// of the licensed edition of Saxon, according to the version of the software that is loaded, and will
92
        /// verify the license key. If false, the Processor will load a default Configuration that gives restricted
93
        /// capability and does not require a license, regardless of which version of the software is actually being run.</param>
94
        /// <param name="loadLocally">This option has no effect at this release.</param>
95

    
96
        public Processor(bool licensedEdition, bool loadLocally)
97
        {
98
            if (licensedEdition)
99
            {
100
                config = JConfiguration.newConfiguration();
101
                schemaManager = new SchemaManager(config);
102
            }
103
            else
104
            {
105
                config = new JConfiguration();
106
            }
107
            config.registerExternalObjectModel(new DotNetObjectModelDefinition());
108
            config.setProcessor(this);
109
        }
110

    
111
        /// <summary>
112
        /// Create a Processor, based on configuration information supplied in a configuration file.
113
        /// </summary>
114
        /// <remarks>
115
        /// Not fully supported in this release: for experimental use only.
116
        /// </remarks>
117
        /// <param name="configurationFile">A stream holding the text of the XML configuration file. Details of the file format
118
        /// can be found in the Saxon documentation.</param>
119
        /// 
120

    
121
        public Processor(Stream configurationFile)
122
        {
123
            StreamSource ss = new StreamSource(new DotNetInputStream(configurationFile));
124
            config = JConfiguration.readConfiguration(ss);
125
            config.registerExternalObjectModel(new DotNetObjectModelDefinition());
126
            config.setProcessor(this);
127
        }
128

    
129

    
130
        /// <summary>
131
        /// Get the full name of the Saxon product version implemented by this Processor
132
        /// </summary>
133

    
134
        public string ProductTitle
135
        {
136
            get { return JVersion.getProductTitle(); }
137
        }
138

    
139
        /// <summary>
140
        /// Get the Saxon product version number (for example, "9.2.0.2")
141
        /// </summary>
142

    
143
        public string ProductVersion
144
        {
145
            get { return JVersion.getProductVersion(); }
146
        }
147

    
148
        /// <summary>
149
        /// Get the Saxon product edition (for example, "EE" for Enterprise Edition)
150
        /// </summary>
151
        /// 
152

    
153
        public string Edition
154
        {
155
            get { return config.getEditionCode(); }
156
        }
157

    
158

    
159
        /// <summary>
160
        /// Indicates whether the Processor is schema-aware. In Saxon 9.2, returns true if using Saxon
161
        /// Enterprise Edition.
162
        /// </summary>
163
        /// <remarks>
164
        /// Deprecated since Saxon 9.2; schema-awareness is not directly a property of a Processor any more.
165
        /// Use the Edition property to determine which Saxon edition is in use.
166
        /// </remarks>
167

    
168
        public bool IsSchemaAware
169
        {
170
            get { return config.getEditionCode() == "EE"; }
171
        }
172

    
173
        /// <summary>
174
        /// Gets the SchemaManager for the Processor. Returns null
175
        /// if the Processor is not schema-aware.
176
        /// </summary>
177

    
178
        public SchemaManager SchemaManager
179
        {
180
            get { return schemaManager; }
181
        }
182

    
183
        /// <summary>
184
        /// An XmlResolver, which will be used while compiling and running queries, 
185
        /// XPath expressions, and stylesheets, if no other XmlResolver is nominated
186
        /// </summary>
187
        /// <remarks>
188
        /// <para>By default an <c>XmlUrlResolver</c> is used. This means that the responsibility
189
        /// for resolving and dereferencing URIs rests with the .NET platform, not with the
190
        /// GNU Classpath.</para>
191
        /// <para>When Saxon invokes a user-written <c>XmlResolver</c>, the <c>GetEntity</c> method
192
        /// may return any of: a <c>System.IO.Stream</c>; a <c>System.IO.TextReader</c>; or a
193
        /// <c>java.xml.transform.Source</c>.</para>
194
        /// </remarks>
195

    
196
        public XmlResolver XmlResolver
197
        {
198
            get
199
            {
200
                return ((DotNetURIResolver)config.getURIResolver()).getXmlResolver();
201
            }
202
            set
203
            {
204
                config.setURIResolver(new DotNetURIResolver(value));
205
            }
206
        }
207

    
208
        /// <summary>
209
        /// Create a new <c>DocumentBuilder</c>, which may be used to build XDM documents from
210
        /// a variety of sources.
211
        /// </summary>
212
        /// <returns>A new <c>DocumentBuilder</c></returns>
213

    
214
        public DocumentBuilder NewDocumentBuilder()
215
        {
216
            DocumentBuilder builder = new DocumentBuilder(this);
217
            builder.XmlResolver = XmlResolver;
218
            return builder;
219
        }
220

    
221
        /// <summary>
222
        /// Create a new XQueryCompiler, which may be used to compile XQuery queries.
223
        /// </summary>
224
        /// <remarks>
225
        /// The returned XQueryCompiler retains a live link to the Processor, and
226
        /// may be affected by subsequent changes to the Processor.
227
        /// </remarks>
228
        /// <returns>A new XQueryCompiler</returns>
229

    
230
        public XQueryCompiler NewXQueryCompiler()
231
        {
232
            return new XQueryCompiler(this);
233
        }
234

    
235
        /// <summary>
236
        /// Create a new XsltCompiler, which may be used to compile XSLT stylesheets.
237
        /// </summary>
238
        /// <remarks>
239
        /// The returned XsltCompiler retains a live link to the Processor, and
240
        /// may be affected by subsequent changes to the Processor.
241
        /// </remarks>
242
        /// <returns>A new XsltCompiler</returns>
243

    
244
        public XsltCompiler NewXsltCompiler()
245
        {
246
            return new XsltCompiler(config);
247
        }
248

    
249
        /// <summary>
250
        /// Create a new XPathCompiler, which may be used to compile XPath expressions.
251
        /// </summary>
252
        /// <remarks>
253
        /// The returned XPathCompiler retains a live link to the Processor, and
254
        /// may be affected by subsequent changes to the Processor.
255
        /// </remarks>
256
        /// <returns>A new XPathCompiler</returns>
257

    
258
        public XPathCompiler NewXPathCompiler()
259
        {
260
            return new XPathCompiler(config);
261
        }
262

    
263
        /// <summary>
264
        /// The XML version used in this <c>Processor</c> (for example, this determines what characters
265
        /// are permitted in a name)
266
        /// </summary>
267
        /// <remarks>
268
        /// The value must be 1.0 or 1.1, as a <c>decimal</c>. The default version is currently 1.0, but may
269
        /// change in the future.
270
        /// </remarks>
271

    
272
        public decimal XmlVersion
273
        {
274
            get
275
            {
276
                return (config.getXMLVersion() == JConfiguration.XML10 ? 1.0m : 1.1m);
277
            }
278
            set
279
            {
280
                if (value == 1.0m)
281
                {
282
                    config.setXMLVersion(JConfiguration.XML10);
283
                }
284
                else if (value == 1.1m)
285
                {
286
                    config.setXMLVersion(JConfiguration.XML11);
287
                }
288
                else
289
                {
290
                    throw new ArgumentException("Invalid XML version: " + value);
291
                }
292
            }
293
        }
294

    
295
        /// <summary>
296
        /// Register a named collection. A collection is identified by a URI (the collection URI),
297
        /// and its content is represented by an <c>IEnumerable</c> that enumerates the contents
298
        /// of the collection. The values delivered by this enumeration are Uri values, which 
299
        /// can be mapped to nodes using the registered <c>XmlResolver</c>.
300
        /// </summary>
301
        /// <param name="collectionUri">The URI used to identify the collection in a call
302
        /// of the XPath <c>collection()</c> function. The default collection is registered
303
        /// by supplying null as the value of this argument (this is the collection returned
304
        /// when the XPath <c>collection()</c> function is called with no arguments).</param> 
305
        /// <param name="contents">An enumerable object that represents the contents of the
306
        /// collection, as a sequence of document URIs. The enumerator returned by this
307
        /// IEnumerable object must return instances of the Uri class.</param>
308
        /// <remarks>
309
        /// <para>Collections should be stable: that is, two calls to retrieve the same collection URI
310
        /// should return the same sequence of document URIs. This requirement is imposed by the
311
        /// W3C specifications, but in the case of a user-defined collection it is not enforced by
312
        /// the Saxon product.</para>
313
        /// <para>A collection may be "unregistered" by providing null as the value of the
314
        /// contents argument. A collection may be replaced by specifying the URI of an existing
315
        /// collection.</para>
316
        /// <para>Collections registered with a processor are available to all queries and stylesheets
317
        /// running under the control of that processor. Collections should not normally be registered
318
        /// while queries and transformations are in progress.</para>
319
        /// </remarks>
320
        /// 
321

    
322
        public void RegisterCollection(Uri collectionUri, IEnumerable contents)
323
        {
324
            String u = (collectionUri == null ? null : collectionUri.ToString());
325
            DotNetCollectionURIResolver resolver =
326
                (DotNetCollectionURIResolver)config.getCollectionURIResolver();
327
            resolver.registerCollection(u, contents);
328
        }
329

    
330
        /// <summary>
331
        /// Register an extension function with the Processor
332
        /// </summary>
333
        /// <param name="function">
334
        /// An object that defines the extension function, including its name, arity, arguments types, and
335
        /// a reference to the class that implements the extension function call.
336
        /// </param>
337

    
338
        public void RegisterExtensionFunction(ExtensionFunctionDefinition function)
339
        {
340
            WrappedExtensionFunctionDefinition f = new WrappedExtensionFunctionDefinition(function);
341
            config.registerExtensionFunction(f);
342
        }
343

    
344
        /// <summary>
345
        /// Copy an XdmValue to an XmlDestination
346
        /// </summary>
347
        /// <remarks>
348
        /// This method can be used to copy any kind of <c>XdmValue</c> to any kind
349
        /// of <c>XdmDestination</c>. The supplied <c>XdmValue</c> is first converted
350
        /// to an XML document according to the rules of the XSLT/XQuery serialization
351
        /// specification (for example, if the <c>XdmValue</c> is a sequence of atomic
352
        /// values, they will be turned in a text node in which the values are converted
353
        /// to strings and separated by single spaces). The resulting document is then
354
        /// written to the supplied <c>XmlDestination</c>.</remarks>
355
        /// <param name="sequence">The value to be written</param>
356
        /// <param name="destination">The destination to which the value should be written</param>
357
        /// 
358

    
359
        public void WriteXdmValue(XdmValue sequence, XmlDestination destination)
360
        {
361
            JResult result = destination.GetResult();
362
            JReceiver r = config.getSerializerFactory().getReceiver(result,
363
                config.makePipelineConfiguration(), destination.GetOutputProperties());
364
            r = new JNamespaceReducer(r);
365
            JTreeReceiver tree = new JTreeReceiver(r);
366
            tree.open();
367
            tree.startDocument(0);
368
            foreach (XdmItem it in sequence)
369
            {
370
                tree.append((Item)it.Unwrap(), 0, JNodeInfo.__Fields.ALL_NAMESPACES);
371
            }
372
            tree.endDocument();
373
            tree.close();
374
        }
375

    
376

    
377
        /// <summary>
378
        /// The underlying Configuration object in the Saxon implementation
379
        /// </summary>
380
        /// <remarks>
381
        /// <para>This property provides access to internal methods in the Saxon engine that are
382
        /// not specifically exposed in the .NET API. In general these methods should be
383
        /// considered to be less stable than the classes in the Saxon.Api namespace.</para> 
384
        /// <para>The internal methods follow
385
        /// Java naming conventions rather than .NET conventions.</para>
386
        /// <para>Information about the returned object (and the objects it provides access to)
387
        /// is included in the Saxon JavaDoc docmentation, available 
388
        /// <link href="http://www.saxonica.com/documentation/javadoc/index.html">online</link>.
389
        /// </para>
390
        /// </remarks>
391

    
392
        public net.sf.saxon.Configuration Implementation
393
        {
394
            get { return config; }
395
        }
396

    
397
        /// <summary>
398
        /// Set a configuration property
399
        /// </summary>
400
        /// <remarks>
401
        /// <para>This method provides the ability to set named properties of the configuration.
402
        /// The property names are set as strings, whose values can be found in the Java
403
        /// class <c>net.sf.saxon.FeatureKeys</c>. The property values are always strings. 
404
        /// Properties whose values are other types are not available via this interface:
405
        /// however all properties have an effective equivalent whose value is a string.
406
        /// Note that on/off properties are set using the strings "true" and "false".</para>
407
        /// <para><i>Method added in Saxon 9.1</i></para>
408
        /// </remarks>
409
        /// <param name="name">The property name</param>
410
        /// <param name="value">The property value</param>
411

    
412
        public void SetProperty(String name, String value)
413
        {
414
            config.setConfigurationProperty(name, value);
415
        }
416

    
417
        /// <summary>
418
        /// Get the value of a configuration property
419
        /// </summary>
420
        /// <remarks>
421
        /// <para>This method provides the ability to get named properties of the configuration.
422
        /// The property names are supplied as strings, whose values can be found in the Java
423
        /// class <c>net.sf.saxon.FeatureKeys</c>. The property values are always returned as strings. 
424
        /// Properties whose values are other types are returned by converting the value to a string.
425
        /// Note that on/off properties are returned using the strings "true" and "false".</para>
426
        /// <para><i>Method added in Saxon 9.1</i></para>
427
        /// </remarks>
428
        /// <param name="name">The property name</param>
429
        /// <returns>The property value, as a string; or null if the property is unset.</returns>
430

    
431
        public String GetProperty(String name)
432
        {
433
            Object obj = config.getConfigurationProperty(name);
434
            return (obj == null ? null : obj.ToString());
435
        }
436

    
437
    }
438

    
439
    /// <summary>
440
    /// The <c>DocumentBuilder</c> class enables XDM documents to be built from various sources.
441
    /// The class is always instantiated using the <c>NewDocumentBuilder</c> method
442
    /// on the <c>Processor</c> object.
443
    /// </summary>
444

    
445
    [Serializable]
446
    public class DocumentBuilder
447
    {
448

    
449
        private Processor processor;
450
        private JConfiguration config;
451
        private XmlResolver xmlResolver;
452
        private SchemaValidationMode validation;
453
        private bool dtdValidation;
454
        private bool lineNumbering;
455
        private WhitespacePolicy whitespacePolicy;
456
        private Uri baseUri;
457
        private QName topLevelElement;
458
        private TreeModel treeModel = TreeModel.Unspecified;
459

    
460
        internal DocumentBuilder(Processor processor)
461
        {
462
            this.processor = processor;
463
            this.config = processor.Implementation;
464
            this.xmlResolver = new XmlUrlResolver();
465
        }
466

    
467
        /// <summary>
468
        /// An XmlResolver, which will be used to resolve URIs of documents being loaded
469
        /// and of references to external entities within those documents (including any external DTD).
470
        /// </summary>
471
        /// <remarks>
472
        /// <para>By default an <c>XmlUrlResolver</c> is used. This means that the responsibility
473
        /// for resolving and dereferencing URIs rests with the .NET platform (and not with the
474
        /// GNU Classpath).</para>
475
        /// <para>When Saxon invokes a user-written <c>XmlResolver</c>, the <c>GetEntity</c> method
476
        /// may return any of: a <c>System.IO.Stream</c>; a <c>System.IO.TextReader</c>; or a
477
        /// <c>java.xml.transform.Source</c>. However, if the <c>XmlResolver</c> is called
478
        /// by the XML parser to resolve external entity references, then it must return an 
479
        /// instance of <c>System.IO.Stream</c>.</para>
480
        /// </remarks>
481

    
482
        public XmlResolver XmlResolver
483
        {
484
            get
485
            {
486
                return xmlResolver;
487
            }
488
            set
489
            {
490
                xmlResolver = value;
491
            }
492
        }
493

    
494
        /// <summary>
495
        /// Determines whether line numbering is enabled for documents loaded using this
496
        /// <c>DocumentBuilder</c>.
497
        /// </summary>
498
        /// <remarks>
499
        /// <para>By default, line numbering is disabled.</para>
500
        /// <para>Line numbering is not available for all kinds of source: in particular,
501
        /// it is not available when loading from an existing XmlDocument.</para>
502
        /// <para>The resulting line numbers are accessible to applications using the
503
        /// extension function saxon:line-number() applied to a node.</para>  
504
        /// <para>Line numbers are maintained only for element nodes; the line number
505
        /// returned for any other node will be that of the most recent element.</para> 
506
        /// </remarks>
507

    
508
        public bool IsLineNumbering
509
        {
510
            get
511
            {
512
                return lineNumbering;
513
            }
514
            set
515
            {
516
                lineNumbering = value;
517
            }
518
        }
519

    
520
        /// <summary>
521
        /// Determines whether schema validation is applied to documents loaded using this
522
        /// <c>DocumentBuilder</c>, and if so, whether it is strict or lax.
523
        /// </summary>
524
        /// <remarks>
525
        /// <para>By default, no schema validation takes place.</para>
526
        /// <para>This option requires the schema-aware version of the Saxon product (Saxon-SA).</para>
527
        /// </remarks>
528

    
529
        public SchemaValidationMode SchemaValidationMode
530
        {
531
            get
532
            {
533
                return validation;
534
            }
535
            set
536
            {
537
                validation = value;
538
            }
539
        }
540

    
541
        /// <summary>
542
        /// The required name of the top level element in a document instance being validated
543
        /// against a schema.
544
        /// </summary>
545
        /// <remarks>
546
        /// <para>If this property is set, and if schema validation is requested, then validation will
547
        /// fail unless the outermost element of the document has the required name.</para>
548
        /// <para>This option requires the schema-aware version of the Saxon product (Saxon-SA).</para>
549
        /// </remarks> 
550

    
551
        public QName TopLevelElementName
552
        {
553
            get
554
            {
555
                return topLevelElement;
556
            }
557
            set
558
            {
559
                topLevelElement = value;
560
            }
561
        }
562

    
563
        /// <summary>
564
        /// Determines whether DTD validation is applied to documents loaded using this
565
        /// <c>DocumentBuilder</c>.
566
        /// </summary>
567
        /// <remarks>
568
        ///
569
        /// <para>By default, no DTD validation takes place.</para>
570
        /// 
571
        /// </remarks>
572

    
573
        public bool DtdValidation
574
        {
575
            get
576
            {
577
                return dtdValidation;
578
            }
579
            set
580
            {
581
                dtdValidation = value;
582
            }
583
        }
584

    
585
        /// <summary>
586
        /// Determines the whitespace stripping policy applied when loading a document
587
        /// using this <c>DocumentBuilder</c>.
588
        /// </summary>
589
        /// <remarks>
590
        /// <para>By default, whitespace text nodes appearing in element-only content
591
        /// are stripped, and all other whitespace text nodes are retained.</para>
592
        /// </remarks>
593

    
594
        public WhitespacePolicy WhitespacePolicy
595
        {
596
            get
597
            {
598
                return whitespacePolicy;
599
            }
600
            set
601
            {
602
                whitespacePolicy = value;
603
            }
604
        }
605

    
606
        ///<summary>
607
        /// The Tree Model implementation to be used for the constructed document. By default
608
        /// the TinyTree is used. The main reason for using the LinkedTree alternative is if
609
        /// updating is required (the TinyTree is not updateable).
610
        ///</summary>
611

    
612
        public TreeModel TreeModel
613
        {
614
            get
615
            {
616
                return treeModel;
617
            }
618
            set
619
            {
620
                treeModel = value;
621
            }
622
        }
623

    
624
        /// <summary>
625
        /// The base URI of a document loaded using this <c>DocumentBuilder</c>.
626
        /// This is used for resolving any relative URIs appearing
627
        /// within the document, for example in references to DTDs and external entities.
628
        /// </summary>
629
        /// <remarks>
630
        /// This information is required when the document is loaded from a source that does not
631
        /// provide an intrinsic URI, notably when loading from a Stream or a TextReader.
632
        /// </remarks>
633

    
634

    
635
        public Uri BaseUri
636
        {
637
            get { return baseUri; }
638
            set { baseUri = value; }
639
        }
640

    
641
        /// <summary>
642
        /// Load an XML document, retrieving it via a URI.
643
        /// </summary>
644
        /// <remarks>
645
        /// <para>Note that the type <c>Uri</c> requires an absolute URI.</para>
646
        /// <para>The URI is dereferenced using the registered <c>XmlResolver</c>.</para>
647
        /// <para>This method takes no account of any fragment part in the URI.</para>
648
        /// <para>The <c>role</c> passed to the <c>GetEntity</c> method of the <c>XmlResolver</c> 
649
        /// is "application/xml", and the required return type is <c>System.IO.Stream</c>.</para>
650
        /// <para>The document located via the URI is parsed using the <c>System.Xml</c> parser.</para>
651
        /// <para>Note that the Microsoft <c>System.Xml</c> parser does not report whether attributes are
652
        /// defined in the DTD as being of type <c>ID</c> and <c>IDREF</c>. This is true whether or not
653
        /// DTD-based validation is enabled. This means that such attributes are not accessible to the 
654
        /// <c>id()</c> and <c>idref()</c> functions.</para>
655
        /// </remarks>
656
        /// <param name="uri">The URI identifying the location where the document can be
657
        /// found. This will also be used as the base URI of the document (regardless
658
        /// of the setting of the <c>BaseUri</c> property).</param>
659
        /// <returns>An <c>XdmNode</c>. This will be
660
        ///  the document node at the root of the tree of the resulting in-memory document. 
661
        /// </returns>
662

    
663
        public XdmNode Build(Uri uri)
664
        {
665
            Object obj = XmlResolver.GetEntity(uri, "application/xml", Type.GetType("System.IO.Stream"));
666
            if (obj is Stream)
667
            {
668
                try
669
                {
670
                    return Build((Stream)obj, uri);
671
                }
672
                finally
673
                {
674
                    ((Stream)obj).Close();
675
                }
676
            }
677
            else
678
            {
679
                throw new ArgumentException("Invalid type of result from XmlResolver.GetEntity: " + obj);
680
            }
681
        }
682

    
683
        /// <summary>
684
        /// Load an XML document supplied as raw (lexical) XML on a Stream.
685
        /// </summary>
686
        /// <remarks>
687
        /// <para>The document is parsed using the Microsoft <c>System.Xml</c> parser if the
688
        /// "http://saxon.sf.net/feature/preferJaxpParser" property on the <c>Processor</c> is set to false;
689
        /// otherwise it is parsed using the Apache Xerces XML parser.</para>
690
        /// <para>Before calling this method, the <c>BaseUri</c> property must be set to identify the
691
        /// base URI of this document, used for resolving any relative URIs contained within it.</para>
692
        /// <para>Note that the Microsoft <c>System.Xml</c> parser does not report whether attributes are
693
        /// defined in the DTD as being of type <c>ID</c> and <c>IDREF</c>. This is true whether or not
694
        /// DTD-based validation is enabled. This means that such attributes are not accessible to the 
695
        /// <c>id()</c> and <c>idref()</c> functions.</para>         
696
        /// </remarks>
697
        /// <param name="input">The Stream containing the XML source to be parsed</param>
698
        /// <returns>An <c>XdmNode</c>, the document node at the root of the tree of the resulting
699
        /// in-memory document
700
        /// </returns>
701

    
702
        public XdmNode Build(Stream input)
703
        {
704
            if (baseUri == null)
705
            {
706
                throw new ArgumentException("No base URI supplied");
707
            }
708
            return Build(input, baseUri);
709
        }
710

    
711
        // Build a document from a given stream, with the base URI supplied
712
        // as an extra argument
713

    
714
        internal XdmNode Build(Stream input, Uri baseUri)
715
        {
716
            Source source;
717
            if (processor.GetProperty("http://saxon.sf.net/feature/preferJaxpParser") == "true")
718
            {
719
                source = new StreamSource(new DotNetInputStream(input), baseUri.ToString());
720
                source = AugmentedSource.makeAugmentedSource(source);
721
                ((AugmentedSource)source).setEntityResolver(new DotNetURIResolver(XmlResolver));
722
            }
723
            else
724
            {
725

    
726
                XmlReaderSettings settings = new XmlReaderSettings();
727
                settings.ProhibitDtd = false;   // must expand entity references
728

    
729
                
730
                //((XmlTextReader)parser).Normalization = true;
731
                switch (whitespacePolicy)
732
                {
733
                    case WhitespacePolicy.PreserveAll:
734
                        settings.IgnoreWhitespace = false;
735
                        //((XmlTextReader)parser).WhitespaceHandling = WhitespaceHandling.All;
736
                        break;
737
                    case WhitespacePolicy.StripAll:
738
                        settings.IgnoreWhitespace = true;
739
                        //((XmlTextReader)parser).WhitespaceHandling = WhitespaceHandling.None;
740
                        break;
741
                    case WhitespacePolicy.StripIgnorable:
742
                        settings.IgnoreWhitespace = true;
743
                        //((XmlTextReader)parser).WhitespaceHandling = WhitespaceHandling.Significant;
744
                        break;
745
                }
746
                if (xmlResolver != null)
747
                {
748
                    settings.XmlResolver = xmlResolver;
749
                }
750
                
751
                settings.ValidationType = (dtdValidation ? ValidationType.DTD : ValidationType.None);
752
                
753
                XmlReader parser = XmlReader.Create(input, settings, baseUri.ToString());
754
                source = new PullSource(new DotNetPullProvider(parser));
755
                source.setSystemId(baseUri.ToString());
756
            }
757
            source = augmentSource(source);
758
            DocumentInfo doc = config.buildDocument(source);
759
            return (XdmNode)XdmValue.Wrap(doc);
760
        }
761

    
762
        /// <summary>
763
        /// Load an XML document supplied using a TextReader.
764
        /// </summary>
765
        /// <remarks>
766
        /// <para>The document is parsed using the Microsoft <c>System.Xml</c> parser if the
767
        /// "http://saxon.sf.net/feature/preferJaxpParser" property on the <c>Processor</c> is set to false;
768
        /// otherwise it is parsed using the Apache Xerces XML parser.</para>
769
        /// <para>Before calling this method, the <c>BaseUri</c> property must be set to identify the
770
        /// base URI of this document, used for resolving any relative URIs contained within it.</para>
771
        /// <para>Note that the Microsoft <c>System.Xml</c> parser does not report whether attributes are
772
        /// defined in the DTD as being of type <c>ID</c> and <c>IDREF</c>. This is true whether or not
773
        /// DTD-based validation is enabled. This means that such attributes are not accessible to the 
774
        /// <c>id()</c> and <c>idref()</c> functions.</para>         
775
        /// </remarks>
776
        /// <param name="input">The <c>TextReader</c> containing the XML source to be parsed</param>
777
        /// <returns>An <c>XdmNode</c>, the document node at the root of the tree of the resulting
778
        /// in-memory document
779
        /// </returns>
780

    
781
        public XdmNode Build(TextReader input)
782
        {
783
            if (baseUri == null)
784
            {
785
                throw new ArgumentException("No base URI supplied");
786
            }
787
            return Build(input, baseUri);
788
        }
789

    
790
        // Build a document from a given stream, with the base URI supplied
791
        // as an extra argument
792

    
793
        internal XdmNode Build(TextReader input, Uri baseUri)
794
        {
795
            Source source;
796
            if (processor.GetProperty("http://saxon.sf.net/feature/preferJaxpParser") == "true")
797
            {
798
                source = new StreamSource(new DotNetReader(input), baseUri.ToString());
799
                source = AugmentedSource.makeAugmentedSource(source);
800
                ((AugmentedSource)source).setEntityResolver(new DotNetURIResolver(XmlResolver));
801
            }
802
            else
803
            {
804

    
805
                XmlReaderSettings settings = new XmlReaderSettings();
806
                settings.ProhibitDtd = false;   // must expand entity references
807

    
808

    
809
                //((XmlTextReader)parser).Normalization = true;
810
                switch (whitespacePolicy)
811
                {
812
                    case WhitespacePolicy.PreserveAll:
813
                        settings.IgnoreWhitespace = false;
814
                        //((XmlTextReader)parser).WhitespaceHandling = WhitespaceHandling.All;
815
                        break;
816
                    case WhitespacePolicy.StripAll:
817
                        settings.IgnoreWhitespace = true;
818
                        //((XmlTextReader)parser).WhitespaceHandling = WhitespaceHandling.None;
819
                        break;
820
                    case WhitespacePolicy.StripIgnorable:
821
                        settings.IgnoreWhitespace = true;
822
                        //((XmlTextReader)parser).WhitespaceHandling = WhitespaceHandling.Significant;
823
                        break;
824
                }
825
                if (xmlResolver != null)
826
                {
827
                    settings.XmlResolver = xmlResolver;
828
                }
829

    
830
                settings.ValidationType = (dtdValidation ? ValidationType.DTD : ValidationType.None);
831

    
832
                XmlReader parser = XmlReader.Create(input, settings, baseUri.ToString());
833
                source = new PullSource(new DotNetPullProvider(parser));
834
                source.setSystemId(baseUri.ToString());
835
            }
836
            source = augmentSource(source);
837
            DocumentInfo doc = config.buildDocument(source);
838
            return (XdmNode)XdmValue.Wrap(doc);
839
        }
840

    
841
        private Source augmentSource(Source source)
842
        {
843
            if (validation != SchemaValidationMode.None)
844
            {
845
                source = AugmentedSource.makeAugmentedSource(source);
846
                if (validation == SchemaValidationMode.Strict)
847
                {
848
                    ((AugmentedSource)source).setSchemaValidationMode(JValidation.STRICT);
849
                }
850
                else if (validation == SchemaValidationMode.Lax)
851
                {
852
                    ((AugmentedSource)source).setSchemaValidationMode(JValidation.LAX);
853
                }
854
                else if (validation == SchemaValidationMode.None)
855
                {
856
                    ((AugmentedSource)source).setSchemaValidationMode(JValidation.STRIP);
857
                }
858
                else if (validation == SchemaValidationMode.Preserve)
859
                {
860
                    ((AugmentedSource)source).setSchemaValidationMode(JValidation.PRESERVE);
861
                }
862
            }
863
            if (topLevelElement != null)
864
            {
865
                source = AugmentedSource.makeAugmentedSource(source);
866
                ((AugmentedSource)source).setTopLevelElement(
867
                    new StructuredQName(
868
                        topLevelElement.Prefix, topLevelElement.Uri, topLevelElement.LocalName));
869
            }
870

    
871
            if (whitespacePolicy != WhitespacePolicy.PreserveAll)
872
            {
873
                source = AugmentedSource.makeAugmentedSource(source);
874
                if (whitespacePolicy == WhitespacePolicy.StripIgnorable)
875
                {
876
                    ((AugmentedSource)source).setStripSpace(Whitespace.IGNORABLE);
877
                }
878
                else
879
                {
880
                    ((AugmentedSource)source).setStripSpace(Whitespace.ALL);
881
                }
882
            }
883
            if (treeModel != TreeModel.Unspecified)
884
            {
885
                source = AugmentedSource.makeAugmentedSource(source);
886
                if (treeModel == TreeModel.TinyTree)
887
                {
888
                    ((AugmentedSource)source).setModel(net.sf.saxon.om.TreeModel.TINY_TREE);
889
                }
890
                else if (treeModel == TreeModel.TinyTreeCondensed)
891
                {
892
                    ((AugmentedSource)source).setModel(net.sf.saxon.om.TreeModel.TINY_TREE_CONDENSED);
893
                }
894
                else
895
                {
896
                    ((AugmentedSource)source).setModel(net.sf.saxon.om.TreeModel.LINKED_TREE);
897
                }
898
            }
899
            if (lineNumbering)
900
            {
901
                source = AugmentedSource.makeAugmentedSource(source);
902
                ((AugmentedSource)source).setLineNumbering(true);
903
            }
904
            if (dtdValidation)
905
            {
906
                source = AugmentedSource.makeAugmentedSource(source);
907
                ((AugmentedSource)source).setDTDValidationMode(JValidation.STRICT);
908
            }
909
            return source;
910
        }
911

    
912
        /// <summary>
913
        /// Load an XML document, delivered using an XmlReader.
914
        /// </summary>
915
        /// <remarks>
916
        /// <para>The XmlReader is responsible for parsing the document; this method builds a tree
917
        /// representation of the document (in an internal Saxon format) and returns its document node.
918
        /// The XmlReader is not required to perform validation but it must expand any entity references.
919
        /// Saxon uses the properties of the <c>XmlReader</c> as supplied.</para>
920
        /// <para>Use of a plain <c>XmlTextReader</c> is discouraged, because it does not expand entity
921
        /// references. This should only be used if you know in advance that the document will contain
922
        /// no entity references (or perhaps if your query or stylesheet is not interested in the content
923
        /// of text and attribute nodes). Instead, with .NET 1.1 use an <c>XmlValidatingReader</c> (with <c>ValidationType</c>
924
        /// set to <c>None</c>). The constructor for <c>XmlValidatingReader</c> is obsolete in .NET 2.0,
925
        /// but the same effect can be achieved by using the <c>Create</c> method of <c>XmlReader</c> with
926
        /// appropriate <c>XmlReaderSettings</c></para>
927
        /// <para>Conformance with the W3C specifications requires that the <c>Normalization</c> property
928
        /// of an <c>XmlTextReader</c> should be set to <c>true</c>. However, Saxon does not insist
929
        /// on this.</para>
930
        /// <para>If the <c>XmlReader</c> performs schema validation, Saxon will ignore any resulting type
931
        /// information. Type information can only be obtained by using Saxon's own schema validator, which
932
        /// will be run if the <c>SchemaValidationMode</c> property is set to <c>Strict</c> or <c>Lax</c></para>
933
        /// <para>Note that the Microsoft <c>System.Xml</c> parser does not report whether attributes are
934
        /// defined in the DTD as being of type <c>ID</c> and <c>IDREF</c>. This is true whether or not
935
        /// DTD-based validation is enabled. This means that such attributes are not accessible to the 
936
        /// <c>id()</c> and <c>idref()</c> functions.</para>
937
        /// <para>Note that setting the <c>XmlResolver</c> property of the <c>DocumentBuilder</c>
938
        /// has no effect when this method is used; if an <c>XmlResolver</c> is required, it must
939
        /// be set on the <c>XmlReader</c> itself.</para>
940
        /// </remarks>
941
        /// <param name="reader">The XMLReader that supplies the parsed XML source</param>
942
        /// <returns>An <c>XdmNode</c>, the document node at the root of the tree of the resulting
943
        /// in-memory document
944
        /// </returns>
945

    
946
        public XdmNode Build(XmlReader reader)
947
        {
948
            PullProvider pp = new DotNetPullProvider(reader);
949
            pp.setPipelineConfiguration(config.makePipelineConfiguration());
950
            // pp = new PullTracer(pp);  /* diagnostics */
951
            Source source = new PullSource(pp);
952
            source.setSystemId(reader.BaseURI);
953
            source = augmentSource(source);
954
            DocumentInfo doc = config.buildDocument(source);
955
            return (XdmNode)XdmValue.Wrap(doc);
956
        }
957

    
958
        /// <summary>
959
        /// Load an XML DOM document, supplied as an <c>XmlNode</c>, into a Saxon XdmNode.
960
        /// </summary>
961
        /// <remarks>
962
        /// <para>
963
        /// The returned document will contain only the subtree rooted at the supplied node.
964
        /// </para>
965
        /// <para>
966
        /// This method copies the DOM tree to create a Saxon tree. See the <c>Wrap</c> method for
967
        /// an alternative that creates a wrapper around the DOM tree, allowing it to be modified in situ.
968
        /// </para>
969
        /// </remarks>
970
        /// <param name="source">The DOM Node to be copied to form a Saxon tree</param>
971
        /// <returns>An <c>XdmNode</c>, the document node at the root of the tree of the resulting
972
        /// in-memory document
973
        /// </returns>
974

    
975
        public XdmNode Build(XmlNode source)
976
        {
977
            return Build(new XmlNodeReader(source));
978
        }
979

    
980
        /// <summary>
981
        /// Wrap an XML DOM document, supplied as an <c>XmlNode</c>, as a Saxon XdmNode.
982
        /// </summary>
983
        /// <remarks>
984
        /// <para>
985
        /// This method must be applied at the level of the Document Node. Unlike the
986
        /// <c>Build</c> method, the original DOM is not copied. This saves memory and
987
        /// time, but it also means that it is not possible to perform operations such as
988
        /// whitespace stripping and schema validation.
989
        /// </para>
990
        /// </remarks>
991
        /// <param name="doc">The DOM document node to be wrapped</param>
992
        /// <returns>An <c>XdmNode</c>, the Saxon document node at the root of the tree of the resulting
993
        /// in-memory document
994
        /// </returns>
995

    
996
        public XdmNode Wrap(XmlDocument doc)
997
        {
998
            String baseu = (baseUri == null ? null : baseUri.ToString());
999
            JDocumentWrapper wrapper = new JDocumentWrapper(doc, baseu, config);
1000
            return (XdmNode)XdmValue.Wrap(wrapper);
1001
        }
1002

    
1003

    
1004
    }
1005

    
1006

    
1007
    /// <summary>
1008
    /// Enumeration identifying the various Schema validation modes
1009
    /// </summary>
1010

    
1011
    public enum SchemaValidationMode
1012
    {
1013
        /// <summary>No validation (or strip validation, which removes existing type annotations)</summary> 
1014
        None,
1015
        /// <summary>Strict validation</summary>
1016
        Strict,
1017
        /// <summary>Lax validation</summary>
1018
        Lax,
1019
        /// <summary>Validation mode preserve, which preserves any existing type annotations</summary>
1020
        Preserve,
1021
        /// <summary>Unspecified validation: this means that validation is defined elsewhere, for example in the
1022
        /// Saxon Configuration</summary>
1023
        Unspecified
1024
    }
1025

    
1026
    /// <summary>
1027
    /// Enumeration identifying the various Whitespace stripping policies
1028
    /// </summary>
1029

    
1030
    public enum WhitespacePolicy
1031
    {
1032
        /// <summary>No whitespace is stripped</summary> 
1033
        PreserveAll,
1034
        /// <summary>Whitespace text nodes appearing in element-only content are stripped</summary>
1035
        StripIgnorable,
1036
        /// <summary>All whitespace text nodes are stripped</summary>
1037
        StripAll
1038
    }
1039

    
1040
    /// <summary>
1041
    /// Enumeration identifying the different tree model implementations
1042
    /// </summary>
1043
    /// 
1044
    public enum TreeModel
1045
    {
1046
        /// <summary>
1047
        /// Saxon TinyTree. This is the default model and is suitable for most purposes.
1048
        /// </summary>
1049
        TinyTree,
1050
        /// <summary>
1051
        /// Saxon Condensed TinyTree. This is a variant of the TinyTree that shares storage for 
1052
        /// duplicated text and attribute nodes. It gives a further saving in space occupied, at the cost
1053
        /// of some increase in the time taken for tree construction.
1054
        /// </summary>
1055
        TinyTreeCondensed,
1056
        /// <summary>
1057
        /// Saxon LinkedTree. This tree model is primarily useful when using XQuery Update, since it is the
1058
        /// only standard tree model to support updates.
1059
        /// </summary>
1060
        LinkedTree,
1061
        /// <summary>
1062
        /// Unspecified tree model. This value is used to indicate that there is no preference for any specific
1063
        /// tree model, which allows the choice to fall back to other interfaces.
1064
        /// </summary>
1065
        Unspecified
1066
    }
1067

    
1068
    internal class DotNetObjectModelDefinition : JDotNetObjectModel
1069
    {
1070

    
1071
        public override bool isXdmValue(object obj)
1072
        {
1073
            return obj is XdmValue;
1074
        }
1075

    
1076
        public override bool isXdmAtomicValueType(Type type)
1077
        {
1078
            return typeof(XdmAtomicValue).IsAssignableFrom(type);
1079
        }
1080

    
1081
        public override bool isXdmValueType(Type type)
1082
        {
1083
            return typeof(XdmValue).IsAssignableFrom(type);
1084
        }
1085

    
1086
        public override JValueRepresentation unwrapXdmValue(object obj)
1087
        {
1088
            return ((XdmValue)obj).Unwrap();
1089
        }
1090

    
1091
        public override object wrapAsXdmValue(JValue value)
1092
        {
1093
            return XdmValue.Wrap(value);
1094
        }
1095

    
1096
        public override bool isXmlNodeType(Type type)
1097
        {
1098
            return typeof(System.Xml.XmlNode).IsAssignableFrom(type);
1099
        }
1100

    
1101
    }
1102

    
1103
}
1104

    
1105
//
1106
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
1107
// you may not use this file except in compliance with the License. You may obtain a copy of the
1108
// License at http://www.mozilla.org/MPL/
1109
//
1110
// Software distributed under the License is distributed on an "AS IS" basis,
1111
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
1112
// See the License for the specific language governing rights and limitations under the License.
1113
//
1114
// The Original Code is: all this file.
1115
//
1116
// The Initial Developer of the Original Code is Michael H. Kay.
1117
//
1118
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
1119
//
1120
// Contributor(s): none.
1121
//
(1-1/10)