Project

Profile

Help

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

he / tags / 9.6.0.7 / hen / csource / api / Saxon.Api / Schema.cs @ aa733b18

1
using System;
2
using System.IO;
3
using System.Xml;
4
using System.Collections;
5
using javax.xml.transform;
6
using javax.xml.transform.stream;
7
using JAugmentedSource = net.sf.saxon.lib.AugmentedSource;
8
using JConfiguration = net.sf.saxon.Configuration;
9
using JController = net.sf.saxon.Controller;
10
using JFeatureKeys = net.sf.saxon.lib.FeatureKeys;
11
using JSchemaURIResolver = net.sf.saxon.lib.SchemaURIResolver;
12
using JReceiver = net.sf.saxon.@event.Receiver;
13
using JAtomicType = net.sf.saxon.type.AtomicType;
14
using JSchemaType = net.sf.saxon.type.SchemaType;
15
using JBuiltInAtomicType = net.sf.saxon.type.BuiltInAtomicType;
16
using JValidation = net.sf.saxon.lib.Validation;
17
using net.sf.saxon;
18
using net.sf.saxon.om;
19
using net.sf.saxon.pull;
20
using net.sf.saxon.@event;
21
using net.sf.saxon.dotnet;
22
using net.sf.saxon.type;
23

    
24

    
25
namespace Saxon.Api
26
{
27

    
28
	/// <summary>
29
	/// A <c>SchemaManager</c> is responsible for compiling schemas and
30
	/// maintaining a cache of compiled schemas that can be used for validating
31
	/// instance documents.
32
	/// </summary>
33
	/// <remarks>
34
	/// <para>To obtain a <c>SchemaManager</c>, use the 
35
	/// <c>SchemaManager</c> property of the <c>Processor</c> object.</para>
36
	/// <para>In a schema-aware Processor there is exactly one
37
	/// <c>SchemaManager</c> (in a non-schema-aware Processor there is none).</para>
38
	/// <para>The cache of compiled schema definitions can include only one schema
39
	/// component (for example a type, or an element declaration) with any given name.
40
	/// An attempt to compile two different schemas in the same namespace will usually
41
	/// therefore fail.</para>
42
	/// <para>As soon as a type definition or element declaration is used for the first
43
	/// time in a validation episode, it is marked as being "sealed": this prevents subsequent
44
	/// modifications to the component. Examples of modifications that are thereby disallowed
45
	/// include adding to the substitution group of an existing element declaration, adding subtypes
46
	/// to an existing type, or redefining components using &lt;xs:redefine&gt;</para>
47
	/// </remarks>
48

    
49
	[Serializable]
50
	public class SchemaManager
51
	{
52

    
53
		private JConfiguration config;
54
		private IList errorList = null;
55
		private net.sf.saxon.s9api.SchemaManager schemaManager;
56
		private Processor processor;
57

    
58
		// internal constructor: the public interface is a factory method
59
		// on the Processor object
60

    
61
		internal SchemaManager(net.sf.saxon.Configuration config)
62
		{
63
			this.config = (JConfiguration)config;
64
		}
65

    
66
		internal SchemaManager(Processor processor)
67
		{
68
			this.processor = processor;
69
			this.schemaManager = processor.JProcessor.getSchemaManager();
70
			this.config = (JConfiguration)processor.Implementation;
71
		}
72

    
73
		/// <summary>
74
		/// The version of the W3C XML Schema Specification handled by this SchemaManager
75
		/// </summary>
76
		/// <remarks>
77
		/// <para>The value must be "1.0" (indicating XML Schema 1.0) or "1.1" (indicating XML Schema 1.1.
78
		/// The default is "1.0". New constructs defined in XSD 1.1 are rejected unless this property
79
		/// is set to "1.1" before compiling the schema.
80
		/// </para>
81
		/// </remarks>
82
		/// 
83
		public String XsdVersion {
84
			get {
85
				return schemaManager.getXsdVersion();
86
			}
87
			set {
88
				schemaManager.setXsdVersion (value);
89
			}
90
		}
91

    
92
		/// <summary>
93
		/// The SchemaResolver is a user-supplied class used for resolving references to
94
		/// schema documents. It applies to references from one schema document to another
95
		/// appearing in <c>xs:import</c>, <c>xs:include</c>, and <c>xs:redefine</c>; to
96
		/// references from an instance document to a schema in <c>xsi:schemaLocation</c> and
97
		/// <c>xsi:noNamespaceSchemaLocation</c>, to <c>xsl:import-schema</c> in XSLT, and to
98
		/// the <c>import schema</c> declaration in XQuery.
99
		/// </summary>
100

    
101
		public SchemaResolver SchemaResolver
102
		{
103
			get
104
			{
105
				JSchemaURIResolver r = schemaManager.getSchemaURIResolver();
106
				if (r is DotNetSchemaURIResolver)
107
				{
108
					return ((DotNetSchemaURIResolver)r).resolver;
109
				}
110
				else
111
				{
112
					return null;
113
				}
114
			}
115
			set
116
			{
117
				schemaManager.setSchemaURIResolver(new DotNetSchemaURIResolver(value));
118
			}
119
		}
120

    
121
		/// <summary>
122
		/// List of errors. The caller may supply an empty list before calling Compile;
123
		/// the processor will then populate the list with error information obtained during
124
		/// the schema compilation. Each error will be included as an object of type StaticError.
125
		/// If no error list is supplied by the caller, error information will be written to
126
		/// the standard error stream.
127
		/// </summary>
128
		/// <remarks>
129
		/// <para>By supplying a custom List with a user-written add() method, it is possible to
130
		/// intercept error conditions as they occur.</para>
131
		/// <para>Note that this error list is used only for errors detected during the compilation
132
		/// of the schema. It is not used for errors detected when using the schema to validate
133
		/// a source document.</para>
134
		/// </remarks>
135

    
136
		public IList ErrorList
137
		{
138
			set
139
			{
140
				errorList = value;
141
				schemaManager.setErrorListener (new ErrorGatherer(errorList));
142
			}
143
			get
144
			{
145
				return errorList;
146
			}
147
		}
148

    
149
		/// <summary>
150
		/// Compile a schema supplied as a Stream. The resulting schema components are added
151
		/// to the cache.
152
		/// </summary>
153
		/// <param name="input">A stream containing the source text of the schema. This method
154
		/// will consume the supplied stream. It is the caller's responsibility to close the stream
155
		/// after use.</param>
156
		/// <param name="baseUri">The base URI of the schema document, for resolving any references to other
157
		/// schema documents</param>        
158

    
159
		public void Compile(Stream input, Uri baseUri)
160
		{
161
			StreamSource ss = new StreamSource(new DotNetInputStream(input));
162
			ss.setSystemId(baseUri.ToString());
163
			schemaManager.load (ss);
164
		}
165

    
166
		/// <summary>
167
		/// Compile a schema, retrieving the source using a URI. The resulting schema components are added
168
		/// to the cache.
169
		/// </summary>
170
		/// <remarks>
171
		/// The document located via the URI is parsed using the <c>System.Xml</c> parser.
172
		/// </remarks>
173
		/// <param name="uri">The URI identifying the location where the schema document can be
174
		/// found</param>
175

    
176
		public void Compile(Uri uri)
177
		{
178
			StreamSource ss = new StreamSource(uri.ToString());
179
			JAugmentedSource aug = JAugmentedSource.makeAugmentedSource(ss);
180
			aug.setPleaseCloseAfterUse(true);
181
			schemaManager.load (aug);
182
		}
183

    
184
		/// <summary>
185
		/// Compile a schema, delivered using an XmlReader. The resulting schema components are added
186
		/// to the cache.
187
		/// </summary>
188
		/// <remarks>
189
		/// The <c>XmlReader</c> is responsible for parsing the document; this method builds a tree
190
		/// representation of the document (in an internal Saxon format) and compiles it.
191
		/// The <c>XmlReader</c> is used as supplied; it is the caller's responsibility to ensure that
192
		/// its settings are appropriate for parsing a schema document (for example, that entity references
193
		/// are expanded and whitespace is retained.)
194
		/// </remarks>
195
		/// <param name="reader">The XmlReader (that is, the XML parser) used to supply the source schema document</param>
196

    
197
		public void Compile(XmlReader reader)
198
		{
199
			PullProvider pp = new DotNetPullProvider(reader);
200
			pp.setPipelineConfiguration(config.makePipelineConfiguration());
201
			// pp = new PullTracer(pp);  /* diagnostics */
202
			PullSource ss = new PullSource(pp);
203
			ss.setSystemId(reader.BaseURI);
204
			schemaManager.load (ss);
205
		}
206

    
207
		/// <summary>
208
		/// Compile a schema document, located at an XdmNode. This may be a document node whose
209
		/// child is an <c>xs:schema</c> element, or it may be
210
		/// the <c>xs:schema</c> element itself. The resulting schema components are added
211
		/// to the cache.
212
		/// </summary>
213
		/// <param name="node">The document node or the outermost element node of a schema document.</param>
214

    
215
		public void Compile(XdmNode node)
216
		{
217
			ErrorGatherer eg = null;
218
			if (errorList != null)
219
			{
220
				eg = new ErrorGatherer(errorList);
221
			}
222
			try
223
			{
224
				config.readInlineSchema((NodeInfo)node.value, null, eg);
225
			}
226
			catch (SchemaException e)
227
			{
228
				throw new StaticError(e);
229
			}
230
		}
231

    
232
		/// <summary>
233
		/// Create a new <c>SchemaValidator</c>, which may be used for validating instance
234
		/// documents.
235
		/// </summary>
236
		/// <remarks>
237
		/// <para>The <c>SchemaValidator</c> uses the cache of schema components held by the
238
		/// <c>SchemaManager</c>. It may also add new components to this cache (for example,
239
		/// when the instance document references a schema using <c>xsi:schemaLocation</c>).
240
		/// It is also affected by changes to the schema cache that occur after the 
241
		/// <c>SchemaValidator</c> is created.</para>
242
		/// <para>When schema components are used for validating instance documents (or for compiling
243
		/// schema-aware queries and stylesheets) they are <i>sealed</i> to prevent subsequent modification.
244
		/// The modifications disallowed once a component is sealed include adding to the substitution group
245
		/// of an element declaration, adding subtypes derived by extension to an existing complex type, and
246
		/// use of <c>&lt;xs:redefine&gt;</c></para>
247
		/// </remarks>
248

    
249
		public SchemaValidator NewSchemaValidator()
250
		{
251
			return new SchemaValidator(config);
252
		}
253

    
254
		/// <summary>
255
		/// Factory method to get an <c>AtomicType</c> object representing the atomic type with a given QName.
256
		/// </summary>
257
		/// <remarks>
258
		/// It is undefined whether two calls on this method supplying the same QName will return the same
259
		/// <c>XdmAtomicType</c> object instance.
260
		/// </remarks>
261
		/// <param name="qname">The QName of the required type</param>
262
		/// <returns>An <c>AtomicType</c> object representing this type if it is present in this schema (and is an
263
		/// atomic type); otherwise, null. </returns>
264

    
265
		public XdmAtomicType GetAtomicType(QName qname)
266
		{
267
			int fp = qname.GetFingerprint(config);
268
			JSchemaType type = config.getSchemaType(fp);
269
			if (type is JBuiltInAtomicType)
270
			{
271
				return XdmAtomicType.BuiltInAtomicType(qname);
272
			}
273
			else if (type is JAtomicType)
274
			{
275
				return new XdmAtomicType((JAtomicType)type);
276
			}
277
			else
278
			{
279
				return null;
280
			}
281
		}
282

    
283
	}
284

    
285
	/// <summary>
286
	/// A <c>SchemaValidator</c> is an object that is used for validating instance documents
287
	/// against a schema. The schema consists of the collection of schema components that are
288
	/// available within the schema cache maintained by the <c>SchemaManager</c>, together with
289
	/// any additional schema components located during the course of validation by means of an
290
	/// <c>xsl:schemaLocation</c> or <c>xsi:noNamespaceSchemaLocation</c> attribute within the
291
	/// instance document.
292
	/// </summary>
293
	/// <remarks>
294
	/// If validation fails, an exception is thrown. If validation succeeds, the validated
295
	/// document can optionally be written to a specified destination. This will be a copy of
296
	/// the original document, augmented with default values for absent elements and attributes,
297
	/// and carrying type annotations derived from the schema processing. Saxon does not deliver
298
	/// the full PSVI as described in the XML schema specifications, only the subset of the
299
	/// PSVI properties featured in the XDM data model.
300
	/// </remarks>    
301

    
302
	[Serializable]
303
	public class SchemaValidator
304
	{
305

    
306
		private JConfiguration config;
307
		private bool lax = false;
308
		private Source source;
309
		private XmlDestination destination;
310
		private IList errorList = null;
311
		private bool useXsiSchemaLocation;
312

    
313
		// internal constructor
314

    
315
		internal SchemaValidator(JConfiguration config)
316
		{
317
			this.config = config;
318
			Object obj = config.getConfigurationProperty(JFeatureKeys.USE_XSI_SCHEMA_LOCATION);
319
			useXsiSchemaLocation = ((java.lang.Boolean)obj).booleanValue();
320
		}
321

    
322
		/// <summary>
323
		/// The validation mode may be either strict or lax. The default is strict;
324
		/// this property is set to indicate that lax validation is required. With strict validation,
325
		/// validation fails if no element declaration can be located for the outermost element. With lax
326
		/// validation, the absence of an element declaration results in the content being considered valid.
327
		/// </summary>
328

    
329
		public bool IsLax
330
		{
331
			get { return lax; }
332
			set { lax = value; }
333
		}
334

    
335
		/// <summary>
336
		/// This property defines whether the schema processor will recognize, and attempt to
337
		/// dereference, any <c>xsi:schemaLocation</c> and <c>xsi:noNamespaceSchemaLocation</c>
338
		/// attributes encountered in the instance document. The default value is true.
339
		/// </summary>
340

    
341
		public Boolean UseXsiSchemaLocation
342
		{
343
			get
344
			{
345
				return useXsiSchemaLocation;
346
			}
347
			set
348
			{
349
				useXsiSchemaLocation = value;
350
			}
351
		}
352

    
353
		/// <summary>
354
		/// Supply the instance document to be validated in the form of a Stream
355
		/// </summary>
356
		/// <param name="source">A stream containing the XML document to be parsed
357
		/// and validated. This stream will be consumed by the validation process,
358
		/// but it will not be closed after use: that is the responsibility of the
359
		/// caller.</param>
360
		/// <param name="baseUri">The base URI to be used for resolving any relative
361
		/// references, for example a reference to an <c>xsi:schemaLocation</c></param>                  
362

    
363
		public void SetSource(Stream source, Uri baseUri)
364
		{
365
			StreamSource ss = new StreamSource(new DotNetInputStream(source));
366
			ss.setSystemId(baseUri.ToString());
367
			this.source = ss;
368
		}
369

    
370
		/// <summary>
371
		/// Supply the instance document to be validated in the form of a Uri reference
372
		/// </summary>
373
		/// <param name="uri">URI of the document to be validated</param>                  
374

    
375
		public void SetSource(Uri uri)
376
		{
377
			StreamSource ss = new StreamSource(uri.ToString());
378
			JAugmentedSource aug = JAugmentedSource.makeAugmentedSource(ss);
379
			aug.setPleaseCloseAfterUse(true);
380
			this.source = aug;
381
		}
382

    
383
		/// <summary>
384
		/// Supply the instance document to be validated, in the form of an XmlReader.
385
		/// </summary>
386
		/// <remarks>
387
		/// The XmlReader is responsible for parsing the document; this method validates it.
388
		/// </remarks>
389
		/// <param name="reader">The <c>XmlReader</c> used to read and parse the instance
390
		/// document being validated. This is used as supplied. For conformance, use of a
391
		/// plain <c>XmlTextReader</c> is discouraged, because it does not expand entity
392
		/// references. This may cause validation failures.
393
		/// </param>
394

    
395
		public void SetSource(XmlReader reader)
396
		{
397
			PullProvider pp = new DotNetPullProvider(reader);
398
			PipelineConfiguration pipe = config.makePipelineConfiguration();
399
			pipe.setUseXsiSchemaLocation(useXsiSchemaLocation);
400
			pp.setPipelineConfiguration(pipe);
401
			// pp = new PullTracer(pp);  /* diagnostics */
402
			PullSource psource = new PullSource(pp);
403
			psource.setSystemId(reader.BaseURI);
404
			this.source = psource;
405
		}
406

    
407
		/// <summary>
408
		/// Supply the instance document to be validated in the form of an XdmNode
409
		/// </summary>
410
		/// <remarks>
411
		/// <para>The supplied node must be either a document node or an element node.
412
		/// If an element node is supplied, then the subtree rooted at this element is
413
		/// validated as if it were a complete document: that is, it must not only conform
414
		/// to the structure required of that element, but any referential constraints
415
		/// (keyref, IDREF) must be satisfied within that subtree.
416
		/// </para>
417
		/// </remarks>
418
		/// <param name="source">The document or element node at the root of the tree
419
		/// to be validated</param>        
420

    
421
		public void SetSource(XdmNode source)
422
		{
423
			this.source = (NodeInfo)source.value;
424
		}
425

    
426
		/// <summary>
427
		/// Supply the destination to hold the validated document. If no destination
428
		/// is supplied, the validated document is discarded.
429
		/// </summary>
430
		/// <remarks>
431
		/// The destination differs from the source in that (a) default values of missing
432
		/// elements and attributes are supplied, and (b) the typed values of elements and
433
		/// attributes are available. However, typed values can only be accessed if the result
434
		/// is represented using the XDM data model, that is, if the destination is supplied
435
		/// as an XdmDestination.
436
		/// </remarks>
437
		/// <param name="destination">
438
		/// The destination to hold the validated document.
439
		/// </param>
440

    
441
		public void SetDestination(XmlDestination destination)
442
		{
443
			this.destination = destination;
444
		}
445

    
446
		/// <summary>
447
		/// List of errors. The caller may supply an empty list before calling Compile;
448
		/// the processor will then populate the list with error information obtained during
449
		/// the schema compilation. Each error will be included as an object of type StaticError.
450
		/// If no error list is supplied by the caller, error information will be written to
451
		/// the standard error stream.
452
		/// </summary>
453
		/// <remarks>
454
		/// <para>By supplying a custom List with a user-written add() method, it is possible to
455
		/// intercept error conditions as they occur.</para>
456
		/// <para>Note that this error list is used only for errors detected while 
457
		/// using the schema to validate a source document. It is not used to report errors
458
		/// in the schema itself.</para>
459
		/// </remarks>
460

    
461
		public IList ErrorList
462
		{
463
			set
464
			{
465
				errorList = value;
466
			}
467
			get
468
			{
469
				return errorList;
470
			}
471
		}
472

    
473

    
474
		/// <summary>
475
		/// Run the validation of the supplied source document, optionally
476
		/// writing the validated document to the supplied destination.
477
		/// </summary>
478

    
479
		public void Run()
480
		{
481
			JAugmentedSource aug = JAugmentedSource.makeAugmentedSource(source);
482
			aug.setSchemaValidationMode(lax ? JValidation.LAX : JValidation.STRICT);
483
			JReceiver receiver;
484
			PipelineConfiguration pipe = config.makePipelineConfiguration();
485
			if (destination == null)
486
			{               
487
				receiver = new Sink(pipe);
488
			}
489
			else if (destination is Serializer)
490
			{
491
				receiver = ((Serializer)destination).GetReceiver(config);
492
			}
493
			else
494
			{
495
				Result result = destination.GetReceiver(pipe);
496
				if (result is JReceiver)
497
				{
498
					receiver = (JReceiver)result;
499
				}
500
				else
501
				{
502
					throw new ArgumentException("Unknown type of destination");
503
				}
504
			}
505
			pipe.setUseXsiSchemaLocation(useXsiSchemaLocation);
506
			receiver.setPipelineConfiguration(pipe);
507
			if (errorList != null)
508
			{
509
				pipe.setErrorListener(new ErrorGatherer(errorList));
510
			}
511
			Sender.send(aug, receiver, null);
512
		}
513

    
514
	}
515

    
516

    
517
	/// <summary>
518
	/// The SchemaResolver is a user-supplied class used for resolving references to
519
	/// schema documents. It applies to references from one schema document to another
520
	/// appearing in <c>xs:import</c>, <c>xs:include</c>, and <c>xs:redefine</c>; to
521
	/// references from an instance document to a schema in <c>xsi:schemaLocation</c> and
522
	/// <c>xsi:noNamespaceSchemaLocation</c>, to <c>xsl:import-schema</c> in XSLT, and to
523
	/// the <c>import schema</c> declaration in XQuery.
524
	/// </summary>
525

    
526

    
527
	public interface SchemaResolver
528
	{
529

    
530
		/// <summary>
531
		/// Given a targetNamespace and a set of location hints, return a set of schema documents.
532
		/// </summary>
533
		/// <param name="targetNamespace">The target namespace of the required schema components</param>
534
		/// <param name="baseUri">The base URI of the module containing the reference to a schema document
535
		/// declaration</param>
536
		/// <param name="locationHints">The sequence of URIs (if any) listed as location hints.
537
		/// In most cases there will only be one; but the <c>import schema</c> declaration in
538
		/// XQuery permits several.</param>
539
		/// <returns>A set of absolute Uris identifying the query modules to be loaded. There is no requirement
540
		/// that these correspond one-to-one with the URIs defined in the <c>locationHints</c>. The 
541
		/// returned URIs will be dereferenced by calling the <c>GetEntity</c> method.
542
		/// </returns>
543

    
544
		/**public**/ Uri[] GetSchemaDocuments(String targetNamespace, Uri baseUri, String[] locationHints);
545

    
546
		/// <summary>
547
		/// Dereference a URI returned by <c>GetModules</c> to retrieve a <c>Stream</c> containing
548
		/// the actual XML schema document.
549
		/// </summary>
550
		/// <param name="absoluteUri">A URI returned by the <code>GetSchemaDocuments</code> method.</param>
551
		/// <returns>Either a <c>Stream</c> or a <c>String</c> containing the query text. 
552
		/// The supplied URI will be used as the base URI of the query module.</returns>
553

    
554
		/**public**/ Object GetEntity(Uri absoluteUri);
555

    
556
	}
557

    
558
	/// <summary>
559
	/// internal class that wraps a (.NET) QueryResolver to create a (Java) SchemaURIResolver
560
	/// </summary>
561

    
562
	internal class DotNetSchemaURIResolver : net.sf.saxon.lib.SchemaURIResolver
563
	{
564

    
565
		internal SchemaResolver resolver;
566
		internal JConfiguration config;
567

    
568
		/// <summary>
569
		/// Initializes a new instance of the <see cref="Saxon.Api.DotNetSchemaURIResolver"/> class.
570
		/// </summary>
571
		/// <param name="resolver">Resolver.</param>
572
		public DotNetSchemaURIResolver(SchemaResolver resolver)
573
		{
574
			this.resolver = resolver;
575
		}
576

    
577
		public void setConfiguration(JConfiguration config)
578
		{
579
			this.config = config;
580
		}
581

    
582
		/// <summary>
583
		/// Resolve the specified targetNamespace, baseURI and locations.
584
		/// </summary>
585
		/// <param name="targetNamespace">Target namespace.</param>
586
		/// <param name="baseURI">BaseURI.</param>
587
		/// <param name="locations">Locations.</param>
588
		public Source[] resolve(String targetNamespace, String baseURI, String[] locations)
589
		{
590
			if (config.isSchemaAvailable(targetNamespace) && !(java.lang.Boolean.valueOf(((java.lang.Object)config.getConfigurationProperty(JFeatureKeys.MULTIPLE_SCHEMA_IMPORTS)).toString()).booleanValue()))
591
			{
592
				return new Source[0];
593
			}
594
			Uri baseU = (baseURI == null ? null : new Uri(baseURI));
595
			Uri[] modules = resolver.GetSchemaDocuments(targetNamespace, baseU, locations);
596
			StreamSource[] ss = new StreamSource[modules.Length];
597
			for (int i = 0; i < ss.Length; i++)
598
			{
599
				ss[i] = new StreamSource();
600
				ss[i].setSystemId(modules[i].ToString());
601
				Object doc = resolver.GetEntity(modules[i]);
602
				if (doc is Stream)
603
				{
604
					ss[i].setInputStream(new DotNetInputStream((Stream)doc));
605
				}
606
				else if (doc is String)
607
				{
608
					ss[i].setReader(new DotNetReader(new StringReader((String)doc)));
609
				}
610
				else
611
				{
612
					throw new ArgumentException("Invalid response from GetEntity()");
613
				}
614
			}
615
			return ss;
616
		}
617
	}
618

    
619

    
620

    
621

    
622

    
623

    
624
}
625

    
626
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
627
// Copyright (c) 2013 Saxonica Limited.
628
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
629
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
630
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
631
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
(9-9/13)