Project

Profile

Help

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

he / src / main / csharp / api / Saxon.Api / XPath.cs @ 2cd2299c

1
using System;
2
using System.Xml;
3
using System.Collections;
4
using System.Globalization;
5
using JIterator = java.util.Iterator;
6
using JSequence = net.sf.saxon.om.Sequence;
7
using JStructuredQName = net.sf.saxon.om.StructuredQName;
8
using JIndependentContext = net.sf.saxon.sxpath.IndependentContext;
9
using JXPathExecutable = net.sf.saxon.s9api.XPathExecutable;
10
using JXPathCompiler = net.sf.saxon.s9api.XPathCompiler;
11
using JXPathSelector = net.sf.saxon.s9api.XPathSelector; 
12
using JXPathVariable = net.sf.saxon.sxpath.XPathVariable;
13
using JStaticProperty = net.sf.saxon.expr.StaticProperty;
14
using JSaxonApiException = net.sf.saxon.s9api.SaxonApiException;
15
using JXPathException = net.sf.saxon.trans.XPathException;
16
using JDotNetComparator = net.sf.saxon.dotnet.DotNetComparator;
17
using JDotNetURIResolver = net.sf.saxon.dotnet.DotNetURIResolver;
18
using JXdmItem = net.sf.saxon.s9api.XdmItem;
19
using System.Collections.Generic;
20

    
21
namespace Saxon.Api
22
{
23

    
24
    /// <summary>
25
	/// An <c>XPathCompiler</c> object allows XPath queries to be compiled.
26
    /// The compiler holds information that represents the static context
27
    /// for the expression.
28
    /// </summary>
29
    /// <remarks>
30
	/// <para>To construct an <c>XPathCompiler</c>, use the factory method
31
	/// <c>NewXPathCompiler</c> on the <see cref="Processor"/> object.</para>
32
	/// <para>An <c>XPathCompiler</c> may be used repeatedly to compile multiple
33
	/// queries. Any changes made to the <c>XPathCompiler</c> (that is, to the
34
    /// static context) do not affect queries that have already been compiled.
35
	/// An <c>XPathCompiler</c> may be used concurrently in multiple threads, but
36
    /// it should not then be modified once initialized.</para>
37
    /// <para> The <code>XPathCompiler</code> has the ability to maintain a cache of compiled
38
    /// expressions. This is active only if enabled by setting the <c>Caching</c> property.
39
    /// If caching is enabled, then the compiler will recognize an attempt to compile
40
    /// the same expression twice, and will avoid the cost of recompiling it. The cache
41
    /// is emptied by any method that changes the static context for subsequent expressions,
42
    /// for example, by setting the <c>BaseUri</c> property. Unless the cache is emptied,
43
    /// it grows indefinitely: compiled expressions are never discarded.</para>
44
    /// </remarks>
45

    
46
    [Serializable]
47
    public class XPathCompiler
48
    {
49

    
50
        private JXPathCompiler compiler;
51
        private Processor processor;
52

    
53
        // internal constructor: the public interface is a factory method
54
        // on the Processor object
55

    
56
        internal XPathCompiler(Processor processor, JXPathCompiler compiler)
57
        {
58
            this.compiler = compiler;
59
            this.processor = processor;
60
        }
61

    
62

    
63

    
64
        /// <summary>
65
        /// Declare the default collation
66
        /// </summary>
67
        /// <param name="uri">the absolute URI of the default collation. This URI must identify a known collation;
68
        /// either one that has been explicitly declared, or one that is recognized implicitly, such as a UCA collation</param>
69
        public void DeclareDefaultCollation(String uri)
70
        {
71
            compiler.declareDefaultCollation(uri);
72
        }
73

    
74
        /// <summary>
75
        /// Declare a namespace for use by the XPath expression.
76
        /// </summary>
77
        /// <param name="prefix">The namespace prefix to be declared. Use
78
        /// a zero-length string to declare the default namespace (that is, the
79
        /// default namespace for elements and types).</param>
80
        /// <param name="uri">The namespace URI. It is possible to specify
81
        /// a zero-length string to "undeclare" a namespace.</param>
82

    
83
        public void DeclareNamespace(String prefix, String uri)
84
        {
85
            compiler.declareNamespace(prefix, uri);
86
        }
87

    
88
        /// <summary>
89
        /// Set the error reporter to be used for reporting static warnings during compilation.
90
		/// By default, the <see cref="ErrorReporter"/> associated with the Saxon Configuration is used.
91
        /// Note that fatal static errors are always reported in the form
92
		/// of an exception thrown by the <see cref="Compile(String)"/> method, so this method only controls
93
        /// the handling of warnings
94
        /// </summary>
95
        /// <remarks>The property IErrorReporter to which warnings will be notified</remarks>
96
        public IErrorReporter WarningHandler {
97
            set {
98
                compiler.setWarningHandler(new ErrorReporterWrapper(value));
99
            }
100

    
101
        }
102

    
103

    
104
        /// <summary>
105
        /// Make available a set of functions defined in an XSLT 3.0 package. All functions
106
		/// defined with <c>visibility="public"</c>
107
		/// (or exposed as public using <c>xsl:expose</c>
108
        /// become part of the static context for an XPath expression created using this
109
		/// <c>XPathCompiler</c>. The functions are added to the search path after all existing
110
        /// functions, including functions added using a previous call on this method.
111
        /// <p>Note that if the library package includes functions that reference stylesheet parameters
112
        /// (or global variables that depend on the context item), then there is no way of supplying
113
        /// values for such parameters; calling such functions will cause a run-time error.</p>
114
        /// </summary>
115
        /// <param name="libraryPackage">the XSLT compiled library package whose functions are to be made available</param>
116
        public void AddXsltFunctionLibrary(XsltPackage libraryPackage) {
117
            compiler.addXsltFunctionLibrary(libraryPackage.GetUnderlyingXsltPackage());
118

    
119
        }
120

    
121
        /// <summary>
122
        /// Get the namespace URI part of a QName provided in lexical form (<c>prefix:localname</c>)
123
        /// </summary>
124
        /// <param name="lexicalName">The lexical QName. This may either be a plain <c>NCName</c> (a local name
125
        /// with no prefix or colon) or a lexical name using a prefix that is bound to a namespace.</param>
126
        /// <param name="useDefault">Set to true if the default namespace for elements and types is to be used
127
        /// in the case where there is no prefix. If false, no prefix means no namespace.</param>
128
        /// <returns>The namespace URI associated with the prefix (or absence thereof) in the supplied
129
        /// lexical QName. The "null namespace" is represented by a zero length string. The method returns null
130
        /// if there is no known binding for the prefix used in the lexical QName.</returns>
131

    
132
        public string GetNamespaceURI(string lexicalName, Boolean useDefault)
133
        {
134
            String[] parts = net.sf.saxon.om.NameChecker.checkQNameParts(net.sf.saxon.value.Whitespace.trimWhitespace(lexicalName));
135

    
136
            return compiler.getUnderlyingStaticContext().getNamespaceResolver().getURIForPrefix(parts[0], useDefault);
137
        }
138

    
139
        /// <summary>
140
        /// Get the <c>Processor</c> from which this <c>XPathCompiler</c> was constructed
141
        /// </summary>
142

    
143
        public Processor Processor
144
        {
145
            get { return processor; }
146
        }
147

    
148
        /// <summary>
149
        /// Import schema definitions for a specified namespace. That is, add the element and attribute declarations 
150
		/// and type definitions contained in a given namespace to the static context for the XPath expression.
151
        /// </summary>
152
        /// <remarks>
153
        /// <para>This method will not cause the schema to be loaded. That must be done separately, using the
154
        /// <c>SchemaManager</c>. This method will not fail if the schema has not been loaded (but in that case
155
        /// the set of declarations and definitions made available to the XPath expression is empty). The schema
156
        /// document for the specified namespace may be loaded before or after this method is called.
157
        /// </para>
158
        /// <para>
159
        /// This method does not bind a prefix to the namespace. That must be done separately, using the
160
        /// <c>DeclareNamespace</c> method.
161
        /// </para>
162
        /// </remarks>
163
        /// <param name="uri">The namespace URI whose declarations and type definitions are to
164
        /// be made available for use within the XPath expression.</param>
165

    
166
        public void ImportSchemaNamespace(String uri)
167
        {
168
            compiler.importSchemaNamespace(uri);
169
        }
170

    
171

    
172
        /// <summary>
173
        /// Escape hatch to the <c>net.sf.saxon.s9api.XPathCompiler</c> object in the underlying Java implementation
174
        /// </summary>
175

    
176
        public JXPathCompiler Implementation
177
        {
178
            get { return compiler; }
179
        }
180

    
181

    
182
        /// <summary>
183
        /// This property indicates whether the XPath expression may contain references to variables that have not been
184
        /// explicitly declared by calling <c>DeclareVariable</c>. The property is false by default (that is, variables
185
        /// must be declared).
186
        /// </summary>
187
        /// <remarks>
188
        /// If undeclared variables are permitted, then it is possible to determine after compiling the expression which
189
        /// variables it refers to by calling the method <c>EnumerateExternalVariables</c> on the <c>XPathExecutable</c> object.
190
        /// </remarks>
191

    
192
        public Boolean AllowUndeclaredVariables
193
        {
194
            get
195
            {
196
                return compiler.isAllowUndeclaredVariables();
197
            }
198
            set
199
            {
200
                compiler.setAllowUndeclaredVariables(value);
201
            }
202
        }
203

    
204
        /// <summary>
205
		/// Say whether XPath expressions compiled using this <c>XPathCompiler</c> are
206
        /// schema-aware. They will automatically be schema-aware if the method
207
        /// <see cref="ImportSchemaNamespace"/> is called. An XPath expression
208
        /// must be marked as schema-aware if it is to handle typed (validated)
209
        /// input documents.
210
        /// </summary>
211

    
212
        public Boolean SchemaAware
213
        {
214
            get {
215
				return compiler.isSchemaAware();
216
            }
217
            set 
218
            {
219
                compiler.setSchemaAware(value);
220
            }
221
        }
222

    
223

    
224
        private int checkSingleChar(String s)
225
        {
226
            int[] e = net.sf.saxon.value.StringValue.expand(s);
227
            if (e.Length != 1)
228
            {
229
                throw new ArgumentException("Attribute \"" + s + "\" should be a single character");
230
            }
231
            return e[0];
232

    
233
        }
234

    
235
        /// <summary>
236
		/// Sets a property of a selected decimal format, for use by the <c>format-number()</c> function.
237
        /// </summary>
238
        /// <remarks>
239
        /// This method checks that the value is valid for the particular property, but it does not
240
        /// check that all the values for the decimal format are consistent (for example, that the
241
        /// decimal separator and grouping separator have different values). This consistency
242
        /// check is performed only when the decimal format is used.
243
        /// </remarks>
244
        /// <param name="format">The name of the decimal format whose property is to be set.
245
        ///  Supply null to set a property of the default (unnamed) decimal format.
246
		///  This correponds to a name used in the third argument of <c>format-number()</c>.</param>
247
        /// <param name="property">The name of the property to set: one of
248
        ///   "decimal-separator", "grouping-separator", "infinity", "NaN",
249
        ///   "minus-sign", "percent", "per-mille", "zero-digit", "digit",
250
        ///   or "pattern-separator".</param>
251
        /// <param name="value">The new value for the property.</param>
252

    
253
        public void SetDecimalFormatProperty(QName format, String property, String value) {
254
            try
255
            {
256
                compiler.setDecimalFormatProperty(format.UnderlyingQName(), property, value);
257
            }
258
            catch (JSaxonApiException e) {
259
                throw new StaticError(e);
260
            }
261

    
262
        }
263

    
264
        /// <summary>
265
        /// Declare a variable for use by the XPath expression. If the expression
266
        /// refers to any variables, then they must be declared here, unless the
267
        /// <c>AllowUndeclaredVariables</c> property has been set to true.
268
        /// </summary>
269
        /// <param name="name">The name of the variable, as a <c>QName</c></param>
270

    
271

    
272
        public void DeclareVariable(QName name)
273
        {
274
            compiler.declareVariable(name.UnderlyingQName());
275
        }
276

    
277
        /// <summary>
278
        /// This property indicates which version of XPath language syntax is accepted. The accepted values
279
        /// are "2.0", "3.0", and "3.1". The default is "3.1".
280
        /// </summary>
281
        /// <remarks>
282
        /// <para>Requesting a value other than 3.1 restricts the XPath grammar to constructs defined
283
        /// in the appropriate version, and uses the appropriate subsets of the functions in the standard
284
        /// function library. However, the semantics of remaining constructs will generally follow the XPath 3.1
285
        /// rules. For example, there is a rule in XPath 2.0 that casting to
286
		/// <c>xs:QName</c> is only permitted if the operand is a string literal, but this is not enforced when
287
        /// this property is set to "2.0".</para>
288
        /// <para>There is no support for XPath 1.0.</para>
289
        /// </remarks>
290

    
291

    
292
        public string XPathLanguageVersion
293
        {
294
			get {
295
                try
296
                {
297
                    return compiler.getLanguageVersion();
298
                }
299
                catch (Exception) {
300
                    throw new StaticError(new net.sf.saxon.trans.XPathException("Unknown XPath version " + compiler.getLanguageVersion()));
301
                }
302
            }
303
            set { 
304
                try
305
                {
306
                    compiler.setLanguageVersion(value);
307
                }
308
                catch (Exception)
309
                {
310
                    throw new StaticError(new net.sf.saxon.trans.XPathException("Unknown XPath version " + value));
311
                }
312
                
313
            }
314
        }
315

    
316

    
317
        /// <summary>
318
        /// The required context item type for the expression. This is used for
319
        /// optimizing the expression at compile time, and to check at run-time
320
        /// that the value supplied for the context item is the correct type.
321
        /// </summary>
322

    
323
        public XdmItemType ContextItemType
324
        {
325
            get { return XdmItemType.MakeXdmItemType( compiler.getRequiredContextItemType().getUnderlyingItemType()); }
326
            set { compiler.setRequiredContextItemType(value.Unwrap()); }
327
        }
328

    
329

    
330
        /// <summary>
331
        /// The base URI of the expression, which forms part of the static context
332
        /// of the expression. This is used for resolving any relative URIs appearing
333
        /// within the expression, for example in the argument to the <c>doc()</c> function.
334
        /// </summary>
335

    
336
        public String BaseUri
337
        {
338
			get { return compiler.getBaseURI().getRawPath(); }
339
            set {
340
               compiler.setBaseURI(new java.net.URI(value)); 
341
            }
342
        }
343

    
344
        /// <summary>
345
        /// XPath 1.0 Backwards Compatibility Mode (that is, XPath 1.0 compatibility mode). 
346
        /// If true, backwards compatibility mode
347
        /// is set. In backwards compatibility mode, more implicit type conversions are
348
        /// allowed in XPath expressions, for example it is possible to compare a number
349
        /// with a string. The default is false (backwards compatibility mode is off).
350
        /// </summary>
351
        /// <remarks>
352
        /// <para>Setting XPath 1.0 compatibility mode does not prevent the use of constructs
353
        /// defined in a later XPath version; rather, it modifies the semantics of some
354
        /// constructs.</para></remarks>
355

    
356
        public Boolean BackwardsCompatible
357
        {
358
            get { return compiler.isBackwardsCompatible(); }
359
            set {
360
                compiler.setBackwardsCompatible(value);
361
            }
362
        }
363

    
364
        /// <summary>
365
        /// This property controls caching of compiled XPath expressions. If caching is enabled,
366
        /// then compiled expressions are saved in a cache and reused if the same expression is compiled
367
        /// again. The cache is cleared (invalidated) if any change is made to the properties of the
368
        /// <c>XPathCompiler</c> that would affect the validity of cached expressions. Caching is disabled
369
        /// by default.
370
        /// </summary>
371

    
372
        public Boolean Caching
373
        {
374
            get { 
375
                return compiler.isCaching(); 
376
            }
377
            set
378
            {
379
                compiler.setCaching(value);
380
            }
381
        }
382

    
383

    
384
		/// <summary>
385
		/// Request fast compilation. Fast compilation will generally be achieved at the expense of run-time performance
386
		/// and quality of diagnostics. Fast compilation is a good trade-off if (a) the expression is known to be correct,
387
		/// and (b) once compiled, it is only executed once against a document of modest size.
388
		/// </summary>
389
		/// <remarks>
390
		/// Set to true to request fast compilation; set to false to revert to the optimization options
391
		/// defined in the Configuration.
392
		/// </remarks>
393
        
394
		public bool FastCompliation
395
        {
396

    
397
            set { compiler.setFastCompilation(value); }
398
            get { return compiler.isFastCompilation(); }
399
        }
400

    
401
        /// <summary>
402
		/// Compile an expression supplied as a <c>String</c>.
403
        /// </summary>
404
        /// <example>
405
        /// <code>
406
        /// XPathExecutable q = compiler.Compile("distinct-values(//*/node-name()");
407
        /// </code>
408
        /// </example>
409
        /// <param name="source">A string containing the source text of the XPath expression</param>
410
        /// <returns>An <c>XPathExecutable</c> which represents the compiled XPath expression object.
411
		/// The <c>XPathExecutable</c> may be run as many times as required, in the same or a different
412
        /// thread. The <c>XPathExecutable</c> is not affected by any changes made to the <c>XPathCompiler</c>
413
        /// once it has been compiled.</returns>
414
        /// <exception cref="StaticError">
415
        /// Throws a <c>Saxon.Api.StaticError</c> if there is any static error in the XPath expression.
416
        /// This includes both syntax errors, semantic errors such as references to undeclared functions or
417
        /// variables, and statically-detected type errors.
418
        /// </exception>
419

    
420
        public XPathExecutable Compile(String source)
421
        {
422
            try { 
423
                JXPathExecutable executable = compiler.compile(source);
424
                return new XPathExecutable(executable);
425
           
426
            }
427
            catch (JSaxonApiException err)
428
            {
429
                throw new StaticError(err);
430
            }
431
        }
432

    
433
        /// <summary>
434
		/// Compile and execute an expression supplied as a <c>String</c>, with a given context item.
435
        /// </summary>
436
        /// <param name="expression">A string containing the source text of the XPath expression</param>
437
        /// <param name="contextItem">The context item to be used for evaluation of the XPath expression.
438
        /// May be null, in which case the expression is evaluated without any context item.</param>
439
        /// <returns>An <c>XdmValue</c> which is the result of evaluating the XPath expression.</returns>
440
        /// <exception cref="StaticError">
441
        /// Throws a <c>Saxon.Api.StaticError</c> if there is any static error in the XPath expression.
442
        /// This includes both syntax errors, semantic errors such as references to undeclared functions or
443
        /// variables, and statically-detected type errors.
444
        /// </exception>
445
        /// <exception cref="DynamicError">
446
        /// Throws a <c>Saxon.Api.DynamicError</c> if there is any dynamic error during evaluation of the XPath expression.
447
        /// This includes, for example, referring to the context item if no context item was supplied.
448
        /// </exception>
449

    
450
        public XdmValue Evaluate(String expression, XdmItem contextItem)
451
        {
452
            try
453
            {
454
                net.sf.saxon.s9api.XdmValue value = compiler.evaluate(expression, contextItem == null ? null : XdmItem.FromXdmItemItemToJXdmItem(contextItem));
455
                return XdmValue.Wrap(value.getUnderlyingValue());
456
            }
457
            catch (JSaxonApiException err)
458
            {
459
                if (err.getCause() is JXPathException)
460
                {
461
                    JXPathException xpathException = (JXPathException)err.getCause();
462
                    if (xpathException.isStaticError())
463
                    {
464
                        throw new StaticError(err);
465
                    }
466
                    else
467
                    {
468
                        throw new DynamicError(err.getMessage());
469
                    }
470
                }
471
                else
472
                {
473
                    throw new StaticError(err);
474
                }
475
            }
476
        }
477

    
478
        /// <summary>
479
		/// Compile and execute an expression supplied as a <c>String</c>, with a given context item, where
480
        /// the expression is expected to return a single item as its result.
481
        /// </summary>
482
        /// <param name="expression">A string containing the source text of the XPath expression</param>
483
        /// <param name="contextItem">The context item to be used for evaluation of the XPath expression.
484
        /// May be null, in which case the expression is evaluated without any context item.</param>
485
        /// <returns>If the XPath expression returns a singleton, then the the <c>XdmItem</c> 
486
        /// which is the result of evaluating the XPath expression. If the expression returns an empty sequence,
487
        /// then null. If the expression returns a sequence containing more than one item, then the first
488
        /// item in the result.</returns>
489
        /// <exception cref="StaticError">
490
        /// Throws a <c>Saxon.Api.StaticError</c> if there is any static error in the XPath expression.
491
        /// This includes both syntax errors, semantic errors such as references to undeclared functions or
492
        /// variables, and statically-detected type errors.
493
        /// </exception>
494
        /// <exception cref="DynamicError">
495
        /// Throws a <c>Saxon.Api.DynamicError</c> if there is any dynamic error during evaluation of the XPath expression.
496
        /// This includes, for example, referring to the context item if no context item was supplied.
497
        /// </exception>
498

    
499
        public XdmItem EvaluateSingle(String expression, XdmItem contextItem)
500
        {
501

    
502
            try
503
            {
504
                JXdmItem value = compiler.evaluateSingle(expression, contextItem == null ? null : XdmItem.FromXdmItemItemToJXdmItem(contextItem));
505
                return (value == null ? null : (XdmItem)XdmValue.Wrap(value.getUnderlyingValue()));
506
            }
507
            catch (JSaxonApiException err)
508
            {
509
                if (err.getCause() is JXPathException)
510
                {
511
                    JXPathException xpathException = (JXPathException)err.getCause();
512
                    if (xpathException.isStaticError())
513
                    {
514
                        throw new StaticError(err);
515
                    }
516
                    else {
517
                        throw new DynamicError(err.getMessage());
518
                    }
519
                }
520
                else
521
                {
522
                    throw new StaticError(err);
523
                }
524
            }
525
            
526
        }
527

    
528
    }
529

    
530
    /// <summary>
531
    /// An <c>XPathExecutable</c> represents the compiled form of an XPath expression. 
532
    /// To evaluate the expression, it must first be loaded to form an <c>XPathSelector</c>.
533
    /// </summary>
534
    /// <remarks>
535
    /// <para>An <c>XPathExecutable</c> is immutable, and therefore thread-safe. It is simplest to
536
    /// load a new <c>XPathSelector</c> each time the expression is to be evaluated. However, the 
537
    /// <c>XPathSelector</c> is serially reusable within a single thread.</para>
538
    /// <para>An <c>XPathExecutable</c> is created by using the <c>Compile</c>
539
    /// method on the <c>XPathCompiler</c> class.</para>
540
    /// </remarks>    
541

    
542
    [Serializable]
543
    public class XPathExecutable
544
    {
545

    
546
        private JXPathExecutable executable;
547

    
548
        // internal constructor
549

    
550
        internal XPathExecutable(JXPathExecutable executable)
551
        {
552
            this.executable = executable;
553
        }
554

    
555
        /// <summary>
556
        /// Get a list of external variables used by the expression. This will include both variables that were explicitly
557
        /// declared to the <c>XPathCompiler</c>, and (if the <c>AllowUndeclaredVariables</c> option was set) variables that
558
        /// are referenced within the expression but not explicitly declared.
559
        /// </summary>
560
        /// <returns>
561
		/// An <c>IEnumerator</c> over the names of the external variables, as instances of <c>QName</c>.
562
		/// </returns>
563
        
564
        public IEnumerator EnumerateExternalVariables()
565
        {
566
            ArrayList list = new ArrayList();
567
            JIterator iter = executable.iterateExternalVariables();
568
            while (iter.hasNext())
569
            {
570
                net.sf.saxon.s9api.QName var = (net.sf.saxon.s9api.QName)iter.next();
571
                list.Add(new QName(var));
572
            }
573
            return list.GetEnumerator();
574
        }
575

    
576
        /// <summary>
577
        /// Escape hatch to the <c>net.sf.saxon.s9api.XPathExecutable</c> object in the underlying Java implementation
578
        /// </summary>
579

    
580
        public JXPathExecutable Implementation
581
        {
582
            get { return executable; }
583
        }
584

    
585
        /// <summary>
586
        /// Get a list of external variables used by the expression. This will include both variables that were explicitly
587
        /// declared to the <c>XPathCompiler</c>, and (if the <c>AllowUndeclaredVariables</c> option was set) variables that
588
        /// are referenced within the expression but not explicitly declared.
589
        /// </summary>
590
        /// <returns>
591
        /// An <c>IEnumerator</c> over the names of the external variables, as instances of <c>QName</c>.
592
        /// </returns>
593

    
594
        public IEnumerator<QName> EnumerateExternalVariables2()
595
        {
596
            IList<QName> list = new List<QName>();
597
            JIterator iter = executable.iterateExternalVariables();
598
            while (iter.hasNext())
599
            {
600
                net.sf.saxon.s9api.QName var = (net.sf.saxon.s9api.QName)iter.next();
601
                list.Add(new QName(var));
602
            }
603
            return list.GetEnumerator();
604
        }
605

    
606

    
607
        /// <summary>
608
        /// Get the required cardinality of a declared variable in the static context of the expression.
609
        /// </summary>
610
        /// <remarks>
611
        /// <para>The result is given as an occurrence indicator, one of:</para>
612
        /// <list>
613
        /// <item>'?' (zero-or-one)</item> 
614
        /// <item>'*' (zero-or-more)</item>
615
        /// <item>'+' (one-or-more)</item>
616
        /// <item>' ' (a single space) (exactly one)</item> 
617
        /// <item>'º' (masculine ordinal indicator, xBA) (exactly zero)</item>
618
        /// </list>
619
        /// <para>The type <c>empty-sequence()</c> can be represented by an occurrence indicator of 'º' with 
620
        /// any item type.</para>
621
        /// <para>If the variable was explicitly declared, this will be the occurrence indicator that was set when the
622
        /// variable was declared. If no item type was set, it will be 
623
        /// <see cref="net.sf.saxon.s9api.OccurrenceIndicator#ZERO_OR_MORE"/>.</para>
624
        /// <para>If the variable was implicitly declared by reference (which can happen only when the
625
        /// <c>allowUndeclaredVariables</c> option is set), the returned type will be
626
        /// <see cref="net.sf.saxon.s9api.OccurrenceIndicator#ZERO_OR_MORE"/>.</para>
627
        /// <para>If no variable with the specified <c>QName</c> has been declared either explicitly or implicitly,
628
        /// the method returns '0'.</para>
629
        /// </remarks>
630
        /// <param name="variableName">the name of a declared variable</param>
631
        /// <returns>The required cardinality, in the form of an occurrence indicator.</returns>
632

    
633

    
634
        public char GetRequiredCardinalityForVariable(QName variableName)
635
        {
636
            JXPathVariable var = ((JIndependentContext)executable.getUnderlyingStaticContext()).getExternalVariable(variableName.ToStructuredQName());
637
            if (var == null)
638
            {
639
                return '0';
640
            }
641
            else
642
            {
643
                return GetOccurrenceIndicator(var.getRequiredType().getCardinality());
644
            }
645
        }
646

    
647

    
648
        //internal method
649

    
650
        internal char GetOccurrenceIndicator(int occurrenceIndicator)
651
        {
652
                switch (occurrenceIndicator)
653
                {
654
                    case JStaticProperty.ALLOWS_ZERO_OR_MORE:
655

    
656
                        return XdmSequenceType.ZERO_OR_MORE;
657

    
658
                    case JStaticProperty.ALLOWS_ONE_OR_MORE:
659

    
660
                        return XdmSequenceType.ONE_OR_MORE;
661

    
662
                    case JStaticProperty.ALLOWS_ZERO_OR_ONE:
663

    
664
                        return XdmSequenceType.ZERO_OR_ONE;
665

    
666
                    case JStaticProperty.EXACTLY_ONE:
667

    
668
                        return XdmSequenceType.ONE;
669

    
670
                    case JStaticProperty.ALLOWS_ZERO:
671

    
672
                        return XdmSequenceType.ZERO;
673

    
674
                    default:
675
                        throw new ArgumentException("Unknown occurrence indicator");
676
                }
677
            
678
        }
679

    
680

    
681
        /// <summary>
682
        /// Load the compiled XPath expression to prepare it for execution.
683
        /// </summary>
684
        /// <returns>
685
        /// An <c>XPathSelector</c>. The returned <c>XPathSelector</c> can be used to
686
        /// set up the dynamic context, and then to evaluate the expression.
687
        /// </returns>
688

    
689
        public XPathSelector Load()
690
        {
691
            JXPathSelector selector = executable.load();
692
            return new XPathSelector(selector);
693
        }
694
    }
695

    
696
    /// <summary inherits="IEnumerable">
697
    /// An <c>XPathSelector</c> represents a compiled and loaded XPath expression ready for execution.
698
    /// The <c>XPathSelector</c> holds details of the dynamic evaluation context for the XPath expression.
699
    /// </summary>
700
    /// <remarks>
701
    /// <para>An <c>XPathSelector</c> should not be used concurrently in multiple threads. It is safe,
702
    /// however, to reuse the object within a single thread to evaluate the same XPath expression several times.
703
    /// Evaluating the expression does not change the context that has been established.</para>
704
    /// <para>An <c>XPathSelector</c> is always constructed by running the <c>Load</c> method of
705
    /// an <c>XPathExecutable</c>.</para>
706
    /// <para>The class <c>XPathSelector</c> implements <c>IEnumerable</c>, so it is possible to
707
	/// enumerate the results in a <c>for</c> expression.</para>
708
    /// </remarks>     
709

    
710
    [Serializable]
711
    public class XPathSelector : IEnumerable
712
    {
713
        JXPathSelector selector;
714

    
715
        // internal constructor
716

    
717
        internal XPathSelector(JXPathSelector selector)
718
        {
719
            this.selector = selector;
720
        }
721

    
722
        /// <summary>
723
        /// The context item for the XPath expression evaluation.
724
        /// </summary>
725
        /// <remarks> This may be either a node or an atomic
726
        /// value. Most commonly it will be a document node, which might be constructed
727
        /// using the <c>Build</c> method of the <c>DocumentBuilder</c> object.
728
        /// </remarks>
729

    
730
        public XdmItem ContextItem
731
        {
732
            get { return (XdmItem)XdmValue.Wrap(selector.getContextItem().getUnderlyingValue()); }
733
            set
734
            {
735
                if (value == null)
736
                {
737
                    throw new ArgumentException("contextItem is null");
738
                }
739
                try
740
                {
741
                    selector.setContextItem(XdmItem.FromXdmItemItemToJXdmItem(value));
742
                }
743
                catch (net.sf.saxon.trans.XPathException err)
744
                {
745
                    throw new StaticError(err);
746
                }
747
            }
748
        }
749

    
750
        /// <summary>
751
        /// Escape hatch to the <c>net.sf.saxon.s9api.XPathSelector</c> object in the underlying Java implementation
752
        /// </summary>
753

    
754
        public JXPathSelector Implementation
755
        {
756
            get { return selector; }
757
        }
758

    
759
        /// <summary>
760
        /// Set the value of a variable
761
        /// </summary>
762
        /// <param name="name">The name of the variable. This must match the name of a variable
763
		/// that was declared to the <c>XPathCompiler</c>. No error occurs if the expression does not
764
        /// actually reference a variable with this name.</param>
765
        /// <param name="value">The value to be given to the variable.</param>
766

    
767
        public void SetVariable(QName name, XdmValue value)
768
        {
769
            try
770
            {
771
                selector.setVariable(name.UnderlyingQName(), value== null ? null : XdmValue.FromGroundedValueToJXdmValue(value.value));
772

    
773
            }
774
            catch (JXPathException err)
775
            {
776
                throw new StaticError(err);
777
            }
778
        }
779

    
780
        /// <summary>
781
        /// The <code>XmlResolver</code> to be used at run-time to resolve and dereference URIs
782
        /// supplied to the <c>doc()</c> function.
783
        /// </summary>
784

    
785
        public XmlResolver InputXmlResolver
786
        {
787
            get
788
            {
789
                return ((JDotNetURIResolver)selector.getURIResolver()).getXmlResolver();
790
            }
791
            set
792
            {
793
                selector.setURIResolver(new JDotNetURIResolver(value));
794
            }
795
        }
796

    
797
        /// <summary>
798
        /// Evaluate the expression, returning the result as an <c>XdmValue</c> (that is,
799
        /// a sequence of nodes, atomic values, and possibly function items such as maps and arrays).
800
        /// </summary>
801
        /// <remarks>
802
        /// Although a singleton result <i>may</i> be represented as an <c>XdmItem</c>, there is
803
        /// no guarantee that this will always be the case. If you know that the expression will return at
804
        /// most one node or atomic value, it is best to use the <c>EvaluateSingle</c> method, which 
805
        /// does guarantee that an <c>XdmItem</c> (or null) will be returned.
806
        /// </remarks>
807
        /// <returns>
808
        /// An <c>XdmValue</c> representing the results of the expression. 
809
        /// </returns>
810
        /// <exception cref="DynamicError">
811
        /// Throws <c>Saxon.Api.DynamicError</c> if the evaluation of the XPath expression fails
812
        /// with a dynamic error.
813
        /// </exception>
814

    
815
        public XdmValue Evaluate()
816
        {
817
            try {
818
                net.sf.saxon.s9api.XdmValue value = selector.evaluate();
819
                return value == null ? null : XdmValue.Wrap(value.getUnderlyingValue());
820
            } catch(JSaxonApiException err) {
821
                throw new DynamicError(err);
822
            }
823
        }
824

    
825
        /// <summary>
826
        /// Evaluate the XPath expression, returning the result as an <c>XdmItem</c> (that is,
827
        /// a single node or atomic value).
828
        /// </summary>
829
        /// <returns>
830
        /// An <c>XdmItem</c> representing the result of the expression, or null if the expression
831
        /// returns an empty sequence. If the expression returns a sequence of more than one item,
832
        /// any items after the first are ignored.
833
        /// </returns>
834
        /// <exception cref="DynamicError">
835
        /// Throws <c>Saxon.Api.DynamicError</c> if the evaluation of the XPath expression fails
836
        /// with a dynamic error.
837
        /// </exception>
838

    
839

    
840
        public XdmItem EvaluateSingle()
841
        {
842

    
843
            try
844
            {
845
                JXdmItem item = selector.evaluateSingle();
846
                return item == null ? null : (XdmItem)XdmValue.Wrap(item.getUnderlyingValue().materialize());
847
            }
848
            catch (JSaxonApiException err)
849
            {
850
                throw new DynamicError(err);
851
            }
852

    
853
        }
854
        
855
        /// <summary>
856
        /// Evaluate the effective boolean value of the XPath expression, returning the result as a <c>Boolean</c>
857
        /// </summary>
858
        /// <returns>
859
        /// A <c>Boolean</c> representing the result of the expression, converted to its
860
		/// effective boolean value as if by applying the XPath <c>boolean()</c> function
861
        /// </returns>
862
        /// <exception cref="DynamicError">
863
        /// Throws <c>Saxon.Api.DynamicError</c> if the evaluation of the XPath expression fails
864
        /// with a dynamic error.
865
        /// </exception>
866

    
867

    
868
        public Boolean EffectiveBooleanValue()
869
        {
870
            try
871
            {
872
                return selector.effectiveBooleanValue();
873
            } catch(JSaxonApiException err) {
874
                throw new DynamicError(err);
875
            }
876
        }
877
        
878

    
879
        /// <summary>
880
        /// Evaluate the expression, returning the result as an <c>IEnumerator</c> (that is,
881
        /// an enumerator over a sequence of nodes and/or atomic values).
882
        /// </summary>
883
        /// <returns>
884
        /// An enumerator over the sequence that represents the results of the expression.
885
        /// Each object in this sequence will be an instance of <c>XdmItem</c>. Note
886
        /// that the expression may be evaluated lazily, which means that a successful response
887
        /// from this method does not imply that the expression has executed successfully: failures
888
        /// may be reported later while retrieving items from the iterator. 
889
        /// </returns>
890
        /// <exception cref="DynamicError">
891
        /// May throw a <c>Saxon.Api.DynamicError</c> if the evaluation of the XPath expression fails
892
        /// with a dynamic error. However, some errors will not be detected during the invocation of this
893
		/// method, but only when stepping through the returned <c>SequenceEnumerator</c>.
894
        /// </exception>
895

    
896
        public IEnumerator GetEnumerator()
897
        {
898
            try {
899
                return new SequenceEnumerator<XdmItem>(selector.iterator());
900
            } catch (net.sf.saxon.s9api.SaxonApiUncheckedException err) {
901
                throw new DynamicError(JXPathException.makeXPathException(err));
902
            }
903
        }
904

    
905
    }
906

    
907
	/// <summary>
908
	/// A set of query parameters on a URI passed to the <c>collection()</c> or <c>document()</c> function.
909
	/// </summary>
910

    
911
    public class URIQueryParameters
912
    {
913

    
914
        private net.sf.saxon.functions.URIQueryParameters uriQueryParameters;
915

    
916

    
917
        public const int ON_ERROR_FAIL = 1;
918
        public const int ON_ERROR_WARNING = 2;
919
        public const int ON_ERROR_IGNORE = 3;
920

    
921
		/// <summary>
922
		/// Create an object representing the query part of a URI
923
		/// </summary>
924
		/// <param name="query">the part of the URI after the "?" symbol</param>
925
		/// <param name="proc">the Saxon Processor</param>
926

    
927
        public URIQueryParameters(String query, Processor proc)
928
        {
929
            uriQueryParameters = new net.sf.saxon.functions.URIQueryParameters(query, proc.Implementation);
930

    
931
        }
932

    
933
        internal net.sf.saxon.functions.URIQueryParameters Implementation() 
934
		{
935
            return uriQueryParameters;
936
        } 
937

    
938
        /* public static FileNameFilter MakeGlobFilter(String value) 
939
        {
940
            return new FileNameFilter(net.sf.saxon.functions.URIQueryParameters.makeGlobFilter(value));
941
        } */
942

    
943
        public int ValidationMode() 
944
		{
945
            return uriQueryParameters.getValidationMode().intValue();
946
        }
947

    
948
        /* public FileNameFilter FileNameFilter
949
        {
950
            get {
951
                return new FileNameFilter(uriQueryParameters.getFilenameFilter());
952
            }
953
            
954
        }*/
955

    
956
        public bool GetRecurse() 
957
		{
958
            return uriQueryParameters.getRecurse().booleanValue();
959
        }
960

    
961
        public int GetOnError() 
962
		{
963
            return uriQueryParameters.getOnError().intValue();
964
        }
965

    
966

    
967
        public bool GetXInclude()
968
        {
969
            return uriQueryParameters.getXInclude().booleanValue();
970
        }
971

    
972

    
973
        public bool GetMeataData()
974
        {
975
            return uriQueryParameters.getMetaData().booleanValue();
976
        }
977

    
978

    
979
        public String ContentType()
980
        {
981
            return uriQueryParameters.getContentType();
982
        }
983

    
984
        public bool GetStable()
985
        {
986
            return uriQueryParameters.getStable().booleanValue();
987
        }
988

    
989
    }
990

    
991
    /*public class FileNameFilter
992
    {
993
        java.io.FilenameFilter filter;
994
        internal FileNameFilter(java.io.FilenameFilter filter) {
995
            this.filter = filter;
996
        }
997
    }*/
998

    
999

    
1000
}
1001

    
1002

    
1003

    
1004
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1005
// Copyright (c) 2020 Saxonica Limited.
1006
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
1007
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
1008
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
1009
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
(9-9/11)