Project

Profile

Help

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

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

1
using System;
2
using System.IO;
3
using System.Xml;
4
using System.Collections;
5
using System.Globalization;
6
using JStreamSource = javax.xml.transform.stream.StreamSource;
7
using JResult = javax.xml.transform.Result;
8
using JTransformerException = javax.xml.transform.TransformerException;
9
using JOutputURIResolver = net.sf.saxon.lib.OutputURIResolver;
10
using JAugmentedSource = net.sf.saxon.lib.AugmentedSource;
11
using JConfiguration = net.sf.saxon.Configuration;
12
using JLocationProvider = net.sf.saxon.@event.LocationProvider;
13
using JPipelineConfiguration = net.sf.saxon.@event.PipelineConfiguration;
14
using JStructuredQName = net.sf.saxon.om.StructuredQName;
15
using JProperties = java.util.Properties;
16
using JSequenceWriter = net.sf.saxon.@event.SequenceWriter;
17
using JSequenceOutputter = net.sf.saxon.@event.SequenceOutputter;
18
using JReceiver = net.sf.saxon.@event.Receiver;
19
using JReceiverOptions = net.sf.saxon.@event.ReceiverOptions;
20
using JCompilerInfo = net.sf.saxon.trans.CompilerInfo;
21
using JExpressionPresenter = net.sf.saxon.trace.ExpressionPresenter;
22
using JValidation = net.sf.saxon.lib.Validation;
23
using JDocumentURI = net.sf.saxon.om.DocumentURI;
24
using JDecimalValue = net.sf.saxon.value.DecimalValue;
25
using JIndependentContext = net.sf.saxon.sxpath.IndependentContext;
26
using JCompilation = net.sf.saxon.style.Compilation;
27
using net.sf.saxon;
28
using JItem = net.sf.saxon.om.Item;
29
using JNodeInfo = net.sf.saxon.om.NodeInfo;
30
using JItemType = net.sf.saxon.type.ItemType;
31
using JNodeName = net.sf.saxon.om.NodeName;
32
using JSchemaType = net.sf.saxon.type.SchemaType;
33
using JDocumentInfo = net.sf.saxon.om.DocumentInfo;
34
using JPullProvider = net.sf.saxon.pull.PullProvider;
35
using JPullSource = net.sf.saxon.pull.PullSource;
36
using JProcInstParser = net.sf.saxon.tree.util.ProcInstParser;
37
using JXsltCompiler = net.sf.saxon.s9api.XsltCompiler;
38
using net.sf.saxon.dotnet;
39
using CharSequence = java.lang.CharSequence;
40
using JBoolean = java.lang.Boolean;
41
using GlobalParameterSet = net.sf.saxon.expr.instruct.GlobalParameterSet;
42
using JXsltTransformer = net.sf.saxon.s9api.XsltTransformer;
43
using JUserFunction = net.sf.saxon.expr.instruct.UserFunction;
44
using JXslt30Transformer = net.sf.saxon.s9api.Xslt30Transformer;
45
using JRoleLocator = net.sf.saxon.expr.parser.RoleLocator;
46
using JStylesheetPackage = net.sf.saxon.style.StylesheetPackage;
47
using JXsltPackage = net.sf.saxon.s9api.XsltPackage;
48
using System.Collections.Generic;
49
using JMap = java.util.Map;
50

    
51

    
52

    
53

    
54
namespace Saxon.Api
55
{
56

    
57
    /// <summary>
58
    /// An <c>XsltCompiler</c> object allows XSLT 2.0 stylesheets to be compiled.
59
    /// The compiler holds information that represents the static context
60
    /// for the compilation.
61
    /// </summary>
62
    /// <remarks>
63
    /// <para>To construct an <c>XsltCompiler</c>, use the factory method
64
    /// <c>NewXsltCompiler</c> on the <c>Processor</c> object.</para>
65
    /// <para>An <c>XsltCompiler</c> may be used repeatedly to compile multiple
66
    /// queries. Any changes made to the <c>XsltCompiler</c> (that is, to the
67
    /// static context) do not affect queries that have already been compiled.
68
    /// An <c>XsltCompiler</c> may be used concurrently in multiple threads, but
69
    /// it should not then be modified once initialized.</para>
70
    /// </remarks>
71

    
72
    [Serializable]
73
    public class XsltCompiler
74
    {
75

    
76
        //private TransformerFactoryImpl factory;
77
        private Processor processor;
78
        //private JConfiguration config;
79
        //private JCompilerInfo info;
80
        //private JIndependentContext env;
81
        private Uri baseUri;
82
		private ErrorGatherer errorGatherer;
83
        private Hashtable variableList = new Hashtable();
84
        private JXsltCompiler xsltCompiler;
85

    
86
        // internal constructor: the public interface is a factory method
87
        // on the Processor object
88

    
89
        internal XsltCompiler(Processor processor)
90
        {
91
            this.processor = processor;
92
            xsltCompiler = processor.JProcessor.newXsltCompiler();
93
			errorGatherer = new ErrorGatherer (new List<StaticError> ());
94
			xsltCompiler.setErrorListener (errorGatherer);
95
			xsltCompiler.setURIResolver (processor.Implementation.getURIResolver());
96
        }
97

    
98
        /// <summary>
99
        /// The base URI of the stylesheet, which forms part of the static context
100
        /// of the stylesheet. This is used for resolving any relative URIs appearing
101
        /// within the stylesheet, for example in <c>xsl:include</c> and <c>xsl:import</c>
102
        /// declarations, in schema locations defined to <c>xsl:import-schema</c>, 
103
        /// or as an argument to the <c>document()</c> or <c>doc()</c> function.
104
        /// </summary>
105
        /// <remarks>
106
        /// This base URI is used only if the input supplied to the <c>Compile</c> method
107
        /// does not provide its own base URI. It is therefore used on the version of the
108
        /// method that supplies input from a <c>Stream</c>. On the version that supplies
109
        /// input from an <c>XmlReader</c>, this base URI is used only if the <c>XmlReader</c>
110
        /// does not have its own base URI.
111
        /// </remarks>
112

    
113

    
114
        public Uri BaseUri
115
        {
116
            get { return baseUri; }
117
            set { baseUri = value; }
118
        }
119

    
120
        /// <summary>
121
        /// Create a collation based on a given <c>CompareInfo</c> and <c>CompareOptions</c>    
122
        /// </summary>
123
        /// <param name="uri">The collation URI to be used within the XPath expression to refer to this collation</param>
124
        /// <param name="compareInfo">The <c>CompareInfo</c>, which determines the language-specific
125
        /// collation rules to be used</param>
126
        /// <param name="options">Options to be used in performing comparisons, for example
127
        /// whether they are to be case-blind and/or accent-blind</param>
128
        /// <param name="isDefault">If true, this collation will be used as the default collation</param>
129

    
130
        public void DeclareCollation(Uri uri, CompareInfo compareInfo, CompareOptions options, Boolean isDefault)
131
        {
132
            DotNetComparator comparator = new DotNetComparator(compareInfo, options);
133
            processor.JProcessor.getUnderlyingConfiguration().registerCollation(uri.ToString(), comparator);
134
            
135

    
136
           
137
        }
138

    
139
        /// <summary>
140
        /// Get the Processor from which this XsltCompiler was constructed
141
        /// </summary>
142
        public Processor Processor
143
        {
144
            get { return processor; }
145
            set { processor = value; }
146
        }
147

    
148
        /// <summary>
149
        /// An <c>XmlResolver</c>, which will be used to resolve URI references while compiling
150
        /// a stylesheet
151
        /// </summary>
152
        /// <remarks>
153
        /// If no <c>XmlResolver</c> is set for the <c>XsltCompiler</c>, the <c>XmlResolver</c>
154
        /// is used that was set on the <c>Processor</c> at the time <c>NewXsltCompiler</c>
155
        /// was called.
156
        /// </remarks>
157

    
158
        public XmlResolver XmlResolver
159
        {
160
            get
161
            {
162
				javax.xml.transform.URIResolver resolver = processor.Implementation.getURIResolver ();
163
				if (resolver is DotNetURIResolver) {
164
					return ((DotNetURIResolver)resolver).getXmlResolver ();
165
				} else {
166
					return new XmlUrlResolver();
167
				}
168
                //return ((DotNetURIResolver)xsltCompiler.getUnderlyingCompilerInfo().getURIResolver()).getXmlResolver();
169
            }
170
            set
171
            {
172
                xsltCompiler.getUnderlyingCompilerInfo().setURIResolver(new DotNetURIResolver(value));
173
            }
174
        }
175

    
176
        /// <summary>
177
        /// The <c>SchemaAware</c> property determines whether the stylesheet is schema-aware. By default, a stylesheet
178
        /// is schema-aware if it contains one or more <code>xsl:import-schema</code> declarations. This option allows
179
        /// a stylesheet to be marked as schema-aware even if it does not contain such a declaration.
180
        /// </summary>
181
        /// <remarks>
182
        /// <para>If the stylesheet is not schema-aware, then schema-validated input documents will be rejected.</para>
183
        /// <para>The reason for this option is that it is expensive to generate code that can handle typed input
184
        /// documents when they will never arise in practice.</para>
185
        /// <para>The initial setting of this property is false, regardless of whether or not the <c>Processor</c>
186
        /// is schema-aware. Setting this property to true if the processor is not schema-aware will cause an Exception.</para>
187
        /// </remarks>
188

    
189
        public bool SchemaAware
190
        {
191
            get
192
            {
193
                return xsltCompiler.isSchemaAware();
194
            }
195
            set
196
            {
197
                xsltCompiler.setSchemaAware(value);
198
            }
199
        }
200

    
201
        /// <summary>
202
        /// The <c>XsltLanguageVersion</c> property determines whether the version of the XSLT language specification
203
        /// implemented by the compiler. The values 2.0 and 3.0 refer to the XSLT 2.0 and XSLT 3.0 (formerly XSLT 2.1) specifications.
204
        /// The value 0.0 (which is the initial default) indicates that the value is to be taken from the <c>version</c>
205
        /// attribute of the <c>xsl:stylesheet</c> element.
206
        /// </summary>
207
        /// <remarks>
208
        /// <para>Values that are not numerically equal to one of the above values are rejected.</para>
209
        /// <para>A warning is output (unless suppressed) when the XSLT language version supported by the processor
210
        /// is different from the value of the <c>version</c> attribute of the <c>xsl:stylesheet</c> element.</para>
211
        /// <para>XSLT 3.0 features are supported only in Saxon-PE and Saxon-EE. Setting the value to 3.0 under 
212
        /// Saxon-HE will cause an error if (and only if) the stylesheet actually uses XSLT 3.0 constructs.</para>
213
        /// </remarks>
214

    
215
        public string XsltLanguageVersion
216
        {
217
            get
218
            {
219
				return xsltCompiler.getXsltLanguageVersion ();
220
            }
221
            set
222
            {
223
				xsltCompiler.setXsltLanguageVersion(value);
224
            }
225
        }
226

    
227
        /// <summary>
228
        /// List of errors. The caller should supply an empty list before calling Compile;
229
        /// the processor will then populate the list with error information obtained during
230
        /// the compilation. Each error will be included as an object of type StaticError.
231
        /// If no error list is supplied by the caller, error information will be written to
232
        /// the standard error stream.
233
        /// </summary>
234
        /// <remarks>
235
        /// By supplying a custom List with a user-written add() method, it is possible to
236
        /// intercept error conditions as they occur.
237
        /// </remarks>
238

    
239
        public IList ErrorList
240
        {
241
            set
242
            {
243
				errorGatherer = new ErrorGatherer (value);
244
				xsltCompiler.setErrorListener(errorGatherer);
245
            }
246
            get
247
            {
248
				return errorGatherer.ErrorList;
249
            }
250
        }
251

    
252
        /// <summary>
253
        /// Compile a stylesheet supplied as a Stream.
254
        /// </summary>
255
        /// <example>
256
        /// <code>
257
        /// Stream source = new FileStream("input.xsl", FileMode.Open, FileAccess.Read);
258
        /// XsltExecutable q = compiler.Compile(source);
259
        /// source.Close();
260
        /// </code>
261
        /// </example>
262
        /// <param name="input">A stream containing the source text of the stylesheet</param>
263
        /// <returns>An <c>XsltExecutable</c> which represents the compiled stylesheet object.
264
        /// The XsltExecutable may be loaded as many times as required, in the same or a different
265
        /// thread. The <c>XsltExecutable</c> is not affected by any changes made to the <c>XsltCompiler</c>
266
        /// once it has been compiled.</returns>
267
        /// <remarks>
268
        /// <para>If the stylesheet contains any <c>xsl:include</c> or <c>xsl:import</c> declarations,
269
        /// then the <c>BaseURI</c> property must be set to allow these to be resolved.</para>
270
        /// <para>The stylesheet is contained in the part of the input stream between its current
271
        /// position and the end of the stream. It is the caller's responsibility to close the input 
272
        /// stream after use. If the compilation succeeded, then on exit the stream will be 
273
        /// exhausted; if compilation failed, the current position of the stream on exit is
274
        /// undefined.</para>
275
        /// </remarks>
276

    
277
        public XsltExecutable Compile(Stream input)
278
        {
279
            try
280
            {
281
                JStreamSource ss = new JStreamSource(new DotNetInputStream(input));
282
                if (baseUri != null)
283
                {
284
                    ss.setSystemId(baseUri.ToString());
285
                }
286
					
287
				PreparedStylesheet pss = JCompilation.compileSingletonPackage(processor.Implementation, xsltCompiler.getUnderlyingCompilerInfo(),ss);
288
                return new XsltExecutable(processor, pss);
289
            }
290
            catch (JTransformerException err)
291
            {
292
                throw new StaticError(err);
293
            }
294
        }
295

    
296

    
297
		/// <summary>
298
		/// Compile a stylesheet supplied as a Stream.
299
		/// </summary>
300
		/// <example>
301
		/// <code>
302
		/// Stream source = new FileStream("input.xsl", FileMode.Open, FileAccess.Read);
303
		/// XsltExecutable q = compiler.Compile(source);
304
		/// source.Close();
305
		/// </code>
306
		/// </example>
307
		/// <param name="input">A stream containing the source text of the stylesheet</param>
308
		/// <param name="theBaseUri">Specify the base Uri of the stream</param>
309
		/// <param name="closeStream">Flag to indicate if the stream should be closed in the method</param>
310
		/// <returns>An <c>XsltExecutable</c> which represents the compiled stylesheet object.
311
		/// The XsltExecutable may be loaded as many times as required, in the same or a different
312
		/// thread. The <c>XsltExecutable</c> is not affected by any changes made to the <c>XsltCompiler</c>
313
		/// once it has been compiled.</returns>
314
		/// <remarks>
315
		/// <para>If the stylesheet contains any <c>xsl:include</c> or <c>xsl:import</c> declarations,
316
		/// then the <c>BaseURI</c> property must be set to allow these to be resolved.</para>
317
		/// <para>The stylesheet is contained in the part of the input stream between its current
318
		/// position and the end of the stream. It is the caller's responsibility to close the input 
319
		/// stream after use. If the compilation succeeded, then on exit the stream will be 
320
		/// exhausted; if compilation failed, the current position of the stream on exit is
321
		/// undefined.</para>
322
		/// </remarks>
323
		internal XsltExecutable Compile(Stream input, String theBaseUri, bool closeStream)
324
		{
325
			//See bug 2306
326
			try
327
			{
328
				JStreamSource ss = new JStreamSource(new DotNetInputStream(input));
329
				if (theBaseUri != null)
330
				{
331
					ss.setSystemId(theBaseUri.ToString());
332
				} else {
333
					if(baseUri != null) {
334
						ss.setSystemId(baseUri.ToString());
335
					}
336
				}
337

    
338
				PreparedStylesheet pss = JCompilation.compileSingletonPackage(processor.Implementation, xsltCompiler.getUnderlyingCompilerInfo(),ss);
339
				if(closeStream) {
340
					input.Close();
341
				}
342
				return new XsltExecutable(processor, pss);
343
			}
344
			catch (JTransformerException err)
345
			{
346
				throw new StaticError(err);
347
			}
348
		}
349

    
350

    
351

    
352
	/// <summary>Compile a library package.</summary>
353
	/// <para>The source argument identifies an XML file containing an &lt;xsl:package&gt; element. Any packages
354
    /// on which this package depends must have been made available to the <code>XsltCompiler</code>
355
    /// by importing them using {@link #importPackage}.</para></summary>
356
    /// <param name='input'>source identifies an XML document holding the the XSLT package to be compiled</param>
357
    /// <returns the XsltPackage that results from the compilation. Note that this package
358
    ///is not automatically imported to this <code>XsltCompiler</code>; if the package is required
359
    ///for use in subsequent compilations then it must be explicitly imported.</returns>
360
    /// <remarks><para>@since 9.6</para></remarks>
361
     
362
		public XsltPackage CompilePackage(Stream input)
363
		{
364
			try
365
			{
366
				JStreamSource ss = new JStreamSource(new DotNetInputStream(input));
367
				if (baseUri != null)
368
				{
369
					ss.setSystemId(baseUri.ToString());
370
				}
371

    
372
				//JCompilation compilation = new JCompilation(processor.Implementation, GetUnderlyingCompilerInfo());
373
			
374
				XsltPackage pack = new XsltPackage(processor, xsltCompiler.compilePackage(ss));
375

    
376
				return pack;
377
			}
378
			catch (JTransformerException err)
379
			{
380
				throw new StaticError(err);
381
			}
382
		}
383

    
384

    
385

    
386

    
387
     	/// <summary>Compile a list of packages.</summary>
388
     	/// <param name='input'> sources the collection of packages to be compiled, in the form of an Iterable</param
389
     	/// <returns> the collection of compiled packages, in the form of an Iterable.</returns>
390
     	/// <remarks><para>Since 9.6</para></remarks>
391
     	
392
		public IList<XsltPackage> CompilePackages(IList<Stream> sources)
393
		{
394
			java.util.List sourcesJList = new java.util.ArrayList();
395
			foreach (Stream ss in sources) {
396
				sourcesJList.add(new JStreamSource(new DotNetInputStream(ss)));
397
			
398
			}
399
			java.lang.Iterable resultJList = null;
400

    
401
			try {
402
			
403
				resultJList = xsltCompiler.compilePackages (sourcesJList);
404

    
405

    
406
			} catch(JTransformerException ex){
407
				throw new StaticError (ex);
408
			}
409
			IList<XsltPackage> result = new List<XsltPackage>();
410
			java.util.Iterator iter = resultJList.iterator ();
411

    
412
			for(;iter.hasNext();){
413
				JXsltPackage pp = (JXsltPackage)iter.next ();
414
				result.Add (new XsltPackage(processor, pp));
415
			}
416

    
417
			return result;
418
		}
419

    
420

    
421

    
422
     	/// <summary>Import a library package. Calling this method makes the supplied package available for reference
423
     	/// in the <code>xsl:use-package</code> declaration of subsequent compilations performed using this
424
     	/// <code>XsltCompiler</code>.</summary>
425
     	/// <param name='thePackage'> thePackage the package to be imported</param>
426
     	/// <remarks>since 9.6</remarks>
427

    
428
		public void ImportPackage(XsltPackage thePackage) {
429
			if (thePackage.Processor != this.processor) {
430
				throw new StaticError(new JTransformerException("The imported package and the XsltCompiler must belong to the same Processor"));
431
			}
432
			GetUnderlyingCompilerInfo().getPackageLibrary().addPackage(thePackage.PackageName, thePackage.getUnderlyingPreparedPackage());
433
		}
434

    
435

    
436
        ///<summary>  
437
        ///  Get the underlying CompilerInfo object, which provides more detailed (but less stable) control
438
        ///  over some compilation options
439
        ///  </summary>
440
        /// <returns> the underlying CompilerInfo object, which holds compilation-time options. The methods on
441
        /// this object are not guaranteed stable from release to release.
442
        /// </returns>
443

    
444
        public JCompilerInfo GetUnderlyingCompilerInfo()
445
        {
446
			return xsltCompiler.getUnderlyingCompilerInfo();
447
        }
448

    
449

    
450
        /// <summary>
451
        /// Externally set the value of a static parameter (new facility in XSLT 3.0) 
452
        /// </summary>
453
        /// <param name="name">The name of the parameter, expressed
454
        /// as a QName. If a parameter of this name has been declared in the
455
        /// stylesheet, the given value will be assigned to the variable. If the
456
        /// variable has not been declared, calling this method has no effect (it is
457
        /// not an error).</param>
458
        /// <param name="value">The value to be given to the parameter.
459
        /// If the parameter declaration defines a required type for the variable, then
460
        /// this value will be converted in the same way as arguments to function calls
461
        /// (for example, numeric promotion is applied).</param>
462
        public void SetParameter(QName name, XdmValue value)
463
        {
464
            variableList.Add(name, value);
465
			xsltCompiler.getUnderlyingCompilerInfo().setParameter(name.ToStructuredQName(), value.Unwrap());
466
        }
467

    
468
        /// <summary>
469
        /// Compile a stylesheet supplied as a TextReader.
470
        /// </summary>
471
        /// <example>
472
        /// <code>
473
        /// String ss = "<![CDATA[<xsl:stylesheet version='2.0'>....</xsl:stylesheet>]]>";
474
        /// TextReader source = new StringReader(ss);
475
        /// XsltExecutable q = compiler.Compile(source);
476
        /// source.Close();
477
        /// </code>
478
        /// </example>
479
        /// <param name="input">A <c>TextReader</c> containing the source text of the stylesheet</param>
480
        /// <returns>An <c>XsltExecutable</c> which represents the compiled stylesheet object.
481
        /// The XsltExecutable may be loaded as many times as required, in the same or a different
482
        /// thread. The <c>XsltExecutable</c> is not affected by any changes made to the <c>XsltCompiler</c>
483
        /// once it has been compiled.</returns>
484
        /// <remarks>
485
        /// <para>If the stylesheet contains any <c>xsl:include</c> or <c>xsl:import</c> declarations,
486
        /// then the <c>BaseURI</c> property must be set to allow these to be resolved.</para>
487
        /// <para>The stylesheet is contained in the part of the input stream between its current
488
        /// position and the end of the stream. It is the caller's responsibility to close the 
489
        /// <c>TextReader</c> after use. If the compilation succeeded, then on exit the stream will be 
490
        /// exhausted; if compilation failed, the current position of the stream on exit is
491
        /// undefined.</para>
492
        /// </remarks>
493

    
494
        public XsltExecutable Compile(TextReader input)
495
        {
496
            JStreamSource ss = new JStreamSource(new DotNetReader(input));
497
            if (baseUri != null)
498
            {
499
                ss.setSystemId(baseUri.ToString());
500
            }
501
			PreparedStylesheet pss = JCompilation.compileSingletonPackage(processor.Implementation ,xsltCompiler.getUnderlyingCompilerInfo(), ss);
502
            return new XsltExecutable(processor, pss);
503
        }
504

    
505
		/// <summary>
506
		/// Compile a stylesheet, retrieving the source using a URI.
507
		/// </summary>
508
		/// <remarks>
509
		/// The document located via the URI is parsed using the <c>System.Xml</c> parser. This
510
		/// URI is used as the base URI of the stylesheet: the <c>BaseUri</c> property of the
511
		/// <c>Compiler</c> is ignored.
512
		/// </remarks>
513
		/// <param name="uri">The URI identifying the location where the stylesheet document can be
514
		/// found</param>
515
		/// <returns>An <c>XsltExecutable</c> which represents the compiled stylesheet object.
516
		/// The XsltExecutable may be run as many times as required, in the same or a different
517
		/// thread. The <c>XsltExecutable</c> is not affected by any changes made to the <c>XsltCompiler</c>
518
		/// once it has been compiled.</returns>
519

    
520
		public XsltExecutable Compile(Uri uri)
521
		{
522
			Object obj = XmlResolver.GetEntity(uri, "application/xml", Type.GetType("System.IO.Stream"));
523
			if (obj is Stream)
524
			{
525
				// See bug issue #2306
526
				return Compile ((Stream)obj, uri.ToString(), true);
527
			}
528
			else
529
			{
530
				throw new ArgumentException("Invalid type of result from XmlResolver.GetEntity: " + obj);
531
			}
532
		}
533

    
534
        /// <summary>
535
        /// Compile a stylesheet, delivered using an XmlReader.
536
        /// </summary>
537
        /// <remarks>
538
        /// The <c>XmlReader</c> is responsible for parsing the document; this method builds a tree
539
        /// representation of the document (in an internal Saxon format) and compiles it.
540
        /// The <c>XmlReader</c> will be used as supplied; it is the caller's responsibility to
541
        /// ensure that the settings of the <c>XmlReader</c> are consistent with the requirements
542
        /// of the XSLT specification (for example, that entity references are expanded and whitespace
543
        /// is preserved).
544
        /// </remarks>
545
        /// <remarks>
546
        /// If the <c>XmlReader</c> has a <c>BaseUri</c> property, then that property determines
547
        /// the base URI of the stylesheet module, which is used when resolving any <c>xsl:include</c>
548
        /// or <c>xsl:import</c> declarations. If the <c>XmlReader</c> has no <c>BaseUri</c>
549
        /// property, then the <c>BaseUri</c> property of the <c>Compiler</c> is used instead.
550
        /// An <c>ArgumentNullException</c> is thrown if this property has not been supplied.
551
        /// </remarks>
552
        /// <param name="reader">The XmlReader (that is, the XML parser) used to supply the document containing
553
        /// the principal stylesheet module.</param>
554
        /// <returns>An <c>XsltExecutable</c> which represents the compiled stylesheet object.
555
        /// The XsltExecutable may be run as many times as required, in the same or a different
556
        /// thread. The <c>XsltExecutable</c> is not affected by any changes made to the <c>XsltCompiler</c>
557
        /// once it has been compiled.</returns>
558

    
559

    
560
        public XsltExecutable Compile(XmlReader reader)
561
        {
562
            DotNetPullProvider pp = new DotNetPullProvider(reader);
563
			JPipelineConfiguration pipe = processor.Implementation.makePipelineConfiguration();
564
            pipe.setLocationProvider(pp);
565
            pp.setPipelineConfiguration(pipe);
566
            // pp = new PullTracer(pp);  /* diagnostics */
567
            JPullSource source = new JPullSource(pp);
568
            String baseu = reader.BaseURI;
569
            if (baseu == null || baseu == String.Empty)
570
            {
571
                // if no baseURI is supplied by the XmlReader, use the one supplied to this Compiler
572
                if (baseUri == null)
573
                {
574
                    throw new ArgumentNullException("BaseUri");
575
                }
576
                baseu = baseUri.ToString();
577
                pp.setBaseURI(baseu);
578
            }
579
            source.setSystemId(baseu);
580
			PreparedStylesheet pss = JCompilation.compileSingletonPackage(processor.Implementation, xsltCompiler.getUnderlyingCompilerInfo(), source);
581
            return new XsltExecutable(processor, pss);
582
        }
583

    
584
        /// <summary>
585
        /// Compile a stylesheet, located at an XdmNode. This may be a document node whose
586
        /// child is an <c>xsl:stylesheet</c> or <c>xsl:transform</c> element, or it may be
587
        /// the <c>xsl:stylesheet</c> or <c>xsl:transform</c> element itself.
588
        /// </summary>
589
        /// <param name="node">The document node or the outermost element node of the document
590
        /// containing the principal stylesheet module.</param>
591
        /// <returns>An <c>XsltExecutable</c> which represents the compiled stylesheet object.
592
        /// The XsltExecutable may be run as many times as required, in the same or a different
593
        /// thread. The <c>XsltExecutable</c> is not affected by any changes made to the <c>XsltCompiler</c>
594
        /// once it has been compiled.</returns>
595

    
596
        public XsltExecutable Compile(XdmNode node)
597
        {
598
			PreparedStylesheet pss = JCompilation.compileSingletonPackage(processor.Implementation, xsltCompiler.getUnderlyingCompilerInfo(), node.Implementation);
599
            return new XsltExecutable(processor, pss);
600
        }
601

    
602
        /// <summary>Locate and compile a stylesheet identified by an &lt;?xml-stylesheet?&gt;
603
        /// processing instruction within a source document.
604
        /// </summary>
605
        /// <param name="source">The document node of the source document containing the
606
        /// xml-stylesheet processing instruction.</param>
607
        /// <returns>An <c>XsltExecutable</c> which represents the compiled stylesheet object.</returns>
608
        /// <remarks>There are some limitations in the current implementation. The media type
609
        /// is ignored, as are the other parameters of the xml-stylesheet instruction. The
610
        /// href attribute must either reference an embedded stylesheet within the same
611
        /// document or a non-embedded external stylesheet.</remarks>
612

    
613
        public XsltExecutable CompileAssociatedStylesheet(XdmNode source)
614
        {
615
            // TODO: lift the restrictions
616
            if (source == null || source.NodeKind != XmlNodeType.Document)
617
            {
618
                throw new ArgumentException("Source must be a document node");
619
            }
620
            IEnumerator kids = source.EnumerateAxis(XdmAxis.Child);
621
            QName xmlstyle = new QName("", "xml-stylesheet");
622
            while (kids.MoveNext())
623
            {
624
                XdmNode n = (XdmNode)kids.Current;
625
                if (n.NodeKind == XmlNodeType.ProcessingInstruction &&
626
                    n.NodeName.Equals(xmlstyle))
627
                {
628
                    // TODO: check the media type
629
                    String href = JProcInstParser.getPseudoAttribute(n.StringValue, "href");
630
                    if (href == null)
631
                    {
632
                        throw new DynamicError("xml-stylesheet processing instruction has no href attribute");
633
                    }
634
                    String fragment = null;
635
                    int hash = href.LastIndexOf('#');
636
                    if (hash == 0)
637
                    {
638
                        if (href.Length == 1)
639
                        {
640
                            throw new DynamicError("Relative URI of '#' is invalid");
641
                        }
642
                        fragment = href.Substring(1);
643
                        JNodeInfo target = ((JDocumentInfo)source.value).selectID(fragment, true);
644
                        XdmNode targetWrapper = null;
645
                        if (target == null)
646
                        {
647
                            // There's a problem here because the Microsoft XML parser doesn't
648
                            // report id values, so selectID() will never work. We work around that
649
                            // by looking for an attribute named "id" appearing on an xsl:stylesheet
650
                            // or xsl:transform element
651
                            QName qid = new QName("", "id");
652
                            IEnumerator en = source.EnumerateAxis(XdmAxis.Descendant);
653
                            while (en.MoveNext())
654
                            {
655
                                XdmNode x = (XdmNode)en.Current;
656
                                if (x.NodeKind == XmlNodeType.Element &&
657
                                        x.NodeName.Uri == "http://www.w3.org/1999/XSL/Transform" &&
658
                                        (x.NodeName.LocalName == "stylesheet" || x.NodeName.LocalName == "transform" &&
659
                                        x.GetAttributeValue(qid) == fragment))
660
                                {
661
                                    targetWrapper = x;
662
                                }
663
                            }
664
                        }
665
                        else
666
                        {
667
                            targetWrapper = (XdmNode)XdmValue.Wrap(target);
668
                        }
669
                        if (targetWrapper == null)
670
                        {
671
                            throw new DynamicError("No element with id='" + fragment + "' found");
672
                        }
673
                        return Compile(targetWrapper);
674
                    }
675
                    else if (hash > 0)
676
                    {
677
                        throw new NotImplementedException("href cannot identify an embedded stylesheet in a different document");
678
                    }
679
                    else
680
                    {
681
                        Uri uri = new Uri(n.BaseUri, href);
682
                        return Compile(uri);
683
                    }
684
                }
685
            }
686
            throw new DynamicError("xml-stylesheet processing instruction not found");
687
        }
688
    }
689

    
690
    /// <summary>
691
    /// An <c>XsltExecutable</c> represents the compiled form of a stylesheet. To execute the stylesheet,
692
    /// it must first be loaded to form an <c>XsltTransformer</c>.
693
    /// </summary>
694
    /// <remarks>
695
    /// <para>An <c>XsltExecutable</c> is immutable, and therefore thread-safe. It is simplest to
696
    /// load a new <c>XsltEvaluator</c> each time the stylesheet is to be run. However, the 
697
    /// <c>XsltEvaluator</c> is serially reusable within a single thread.</para>
698
    /// <para>An <c>XsltExecutable</c> is created by using one of the <c>Compile</c>
699
    /// methods on the <c>XsltCompiler</c> class.</para>
700
    /// </remarks>    
701

    
702
    [Serializable]
703
    public class XsltExecutable
704
    {
705

    
706
        private PreparedStylesheet pss;
707
		private Processor processor;
708

    
709
        // internal constructor
710

    
711
        internal XsltExecutable(Processor proc, PreparedStylesheet pss)
712
        {
713
			this.processor = proc;
714
			this.pss = pss;
715
        }
716

    
717
        /// <summary>
718
        /// Load the stylesheet to prepare it for execution.
719
        /// </summary>
720
        /// <returns>
721
        /// An <c>XsltTransformer</c>. The returned <c>XsltTransformer</c> can be used to
722
        /// set up the dynamic context for stylesheet evaluation, and to run the stylesheet.
723
        /// </returns>
724

    
725
        public XsltTransformer Load()
726
        {
727

    
728
			Controller c = pss.newController ();
729
			return new XsltTransformer(c, pss.getCompileTimeParams());
730
        }
731

    
732

    
733

    
734
		/// <summary>
735
		/// Load the stylesheet to prepare it for execution. This version of the load() method
736
		/// creates an <code>Xslt30Transformer</code> which offers interfaces for stylesheet
737
		/// invocation corresponding to those described in the XSLT 3.0 specification. It can be used
738
		/// with XSLT 2.0 or XSLT 3.0 stylesheets, and in both cases it offers new XSLT 3.0 functionality such
739
		/// as the ability to supply parameters to the initial template, or the ability to invoke
740
		/// stylesheet-defined functions, or the ability to return an arbitrary sequence as a result
741
		/// without wrapping it in a document node.
742
		/// </summary>
743
		/// <returns>
744
		/// An <c>Xslt30Transformer</c>. The returned <c>Xslt30Transformer</c> can be used to
745
		/// set up the dynamic context for stylesheet evaluation, and to run the stylesheet.
746
		/// </returns>
747

    
748
		public Xslt30Transformer Load30()
749
		{
750
			Controller c = pss.newController ();
751
			return new Xslt30Transformer(processor, c, pss.getCompileTimeParams());
752
		}
753

    
754
        /// <summary>
755
        /// Output an XML representation of the compiled code of the stylesheet, for purposes of 
756
        /// diagnostics and instrumentation
757
        /// </summary>
758
        /// <param name="destination">The destination for the diagnostic output</param>
759

    
760
        public void Explain(XmlDestination destination)
761
        {
762
            JConfiguration config = pss.getConfiguration();
763
            JResult result = destination.GetReceiver(config.makePipelineConfiguration());
764
            JProperties properties = new JProperties();
765
            properties.setProperty("indent", "yes");
766
            properties.setProperty("{http://saxon.sf.net/}indent-spaces", "2");
767
            JReceiver receiver = config.getSerializerFactory().getReceiver(
768
                result, config.makePipelineConfiguration(), properties);
769
            JExpressionPresenter presenter = new JExpressionPresenter(config, receiver);
770
            pss.explain(presenter);
771
        }
772

    
773
        /// <summary>
774
        /// Escape hatch to the underlying Java implementation object
775
        /// </summary>
776

    
777
        public PreparedStylesheet Implementation
778
        {
779
            get
780
            {
781
                return pss;
782
            }
783
        }
784

    
785

    
786
        /// <summary>
787
        /// Get the names of the xsl:param elements defined in this stylesheet, with details
788
        /// of each parameter including its required type, and whether it is required or optional
789
        /// </summary>
790
        /// <returns>
791
        /// a Dictionary whose keys are the names of global parameters in the stylesheet,
792
        /// and whose values are {@link ParameterDetails} objects giving information about the
793
        /// corresponding parameter.
794
        /// </returns>
795
        public Dictionary<QName, ParameterDetails> GetGlobalParameters()
796
        {
797
            java.util.List globals = pss.getCompiledGlobalVariables();
798
            Dictionary<QName, ParameterDetails> params1 = new Dictionary<QName, ParameterDetails>();
799
			java.util.Iterator iter = globals.iterator();
800
            while (iter.hasNext())
801
            {
802
				net.sf.saxon.expr.instruct.GlobalVariable var = (net.sf.saxon.expr.instruct.GlobalVariable) iter.next ();
803
				if(var is net.sf.saxon.expr.instruct.GlobalParam){
804
					ParameterDetails details = new ParameterDetails(XdmSequenceType.FromSequenceType(var.getRequiredType()), var.isRequiredParam());
805
					params1.Add(QName.FromClarkName(var.getVariableQName().getClarkName()), details);
806
				}
807
                
808
            }
809

    
810
            return params1;
811
        }
812

    
813

    
814

    
815
		/// <summary>
816
		/// Inner class containing information about a global parameter to a compiled stylesheet.
817
		/// </summary>
818
        public class ParameterDetails
819
        {
820

    
821
            private XdmSequenceType type;
822
            private bool isRequired;
823

    
824
			/// <summary>
825
			/// Initializes a new instance of the <see cref="Saxon.Api.XsltExecutable+ParameterDetails"/> class.
826
			/// </summary>
827
			/// <param name="type1">Type1.</param>
828
			/// <param name="isRequired1">If set to <c>true</c> is required1.</param>
829
            public ParameterDetails(XdmSequenceType type1, bool isRequired1)
830
            {
831
                this.type = type1;
832
                this.isRequired = isRequired1;
833
            }
834

    
835
            /**
836
             * Get the declared item type of the parameter
837
             *
838
             * @return the type defined in the <code>as</code> attribute of the <code>xsl:param</code> element,
839
             *         without its occurrence indicator
840
             */
841
			/// <summary>
842
			/// Gets the type of the declared item.
843
			/// </summary>
844
			/// <returns>The type defined in the <code>as</code> attribute of the <code>xsl:param</code> element,
845
			///  without its occurrence indicator</returns>
846
            public XdmItemType getDeclaredItemType()
847
            {
848
                return type.itemType;
849
            }
850

    
851

    
852
			/// <summary>
853
			/// Gets the declared cardinality of the parameter.
854
			/// </summary>
855
			/// <returns>The occurrence indicator from the type appearing in the <code>as</code> attribute
856
			/// of the <code>xsl:param</code> element</returns>
857
            public int getDeclaredCardinality()
858
            {
859
                return type.occurrences;
860
            }
861

    
862
            /**
863
             *
864
             */
865

    
866
            public XdmSequenceType getUnderlyingDeclaredType()
867
            {
868
                return type;
869
            }
870

    
871

    
872
			/// <summary>
873
			/// Ask whether the parameter is required (mandatory) or optional
874
			/// </summary>
875
			/// <return><c>true</c> if the parameter is mandatory (<code>required="yes"</code>), false
876
			///         if it is optional.</return>
877
            public bool IsRequired
878
            {
879
                set { this.isRequired = value; }
880
                get { return this.isRequired; }
881

    
882
            }
883
        }
884

    
885

    
886

    
887

    
888
    }
889

    
890

    
891
    /// <summary inherits="IEnumerable">
892
    /// An <c>XsltTransformer</c> represents a compiled and loaded stylesheet ready for execution.
893
    /// The <c>XsltTransformer</c> holds details of the dynamic evaluation context for the stylesheet.
894
    /// </summary>
895
    /// <remarks>
896
    /// <para>An <c>XsltTransformer</c> should not be used concurrently in multiple threads. It is safe,
897
    /// however, to reuse the object within a single thread to run the same stylesheet several times.
898
    /// Running the stylesheet does not change the context that has been established.</para>
899
    /// <para>An <c>XsltTransformer</c> is always constructed by running the <c>Load</c> method of
900
    /// an <c>XsltExecutable</c>.</para>
901
    /// </remarks>     
902

    
903
    [Serializable]
904
    public class XsltTransformer : XdmDestination
905
    {
906

    
907
        private Controller controller;
908
		private JNodeInfo initialContextNode;
909
        private IResultDocumentHandler resultDocumentHandler;
910
        private IMessageListener messageListener;
911
        private JStreamSource streamSource;
912
		private StandardLogger traceFunctionDestination;
913
        private XmlDestination destination;		
914
		private GlobalParameterSet staticParameter;
915
		private bool baseOutputUriWasSet = false;
916

    
917

    
918
        // internal constructor
919

    
920
		internal XsltTransformer(Controller controller, GlobalParameterSet staticParameter)
921
        {
922
            this.controller = controller;
923
			this.staticParameter = new GlobalParameterSet(staticParameter);
924
        }
925

    
926
        /// <summary>
927
        /// The initial context item for the stylesheet.
928
        /// </summary>
929
        /// <remarks><para>This may be either a node or an atomic
930
        /// value. Most commonly it will be a document node, which might be constructed
931
        /// using the <c>Build</c> method of the <c>DocumentBuilder</c> object.</para>
932
        /// <para>Note that this can be inefficient if the stylesheet uses <c>xsl:strip-space</c>
933
        /// to strip whitespace, or <c>input-type-annotations="strip"</c> to remove type
934
        /// annotations, since this will result in the transformation operating on a virtual document
935
        /// implemented as a view or wrapper of the supplied document.</para>
936
        /// </remarks>
937

    
938
        public XdmNode InitialContextNode
939
        {
940
		get { return (initialContextNode == null ? null : (XdmNode)XdmValue.Wrap(initialContextNode)); }
941
		set { initialContextNode = (value == null ? null : (JNodeInfo)value.Unwrap()); }
942
        }
943

    
944
        /// <summary>
945
        /// Supply the principal input document for the transformation in the form of a stream.
946
        /// </summary>
947
        /// <remarks>
948
        /// <para>If this method is used, the <c>InitialContextNode</c> is ignored.</para>
949
        /// <para>The supplied stream will be consumed by the <c>Run()</c> method.
950
        /// Closing the input stream after use is the client's responsibility.</para>
951
        /// <para>A base URI must be supplied in all cases. It is used to resolve relative
952
        /// URI references appearing within the input document.</para>
953
        /// <para>Schema validation is applied to the input document according to the value of
954
        /// the <c>SchemaValidationMode</c> property.</para>
955
        /// <para>Whitespace stripping is applied according to the value of the
956
        /// <c>xsl:strip-space</c> and <c>xsl:preserve-space</c> declarations in the stylesheet.</para>
957
        /// </remarks>
958
        /// <param name="input">
959
        /// The stream containing the source code of the principal input document to the transformation. The document
960
        /// node at the root of this document will be the initial context node for the transformation.
961
        /// </param>
962
        /// <param name="baseUri">
963
        /// The base URI of the principal input document. This is used for example by the <c>document()</c>
964
        /// function if the document contains links to other documents in the form of relative URIs.</param>
965

    
966
        public void SetInputStream(Stream input, Uri baseUri)
967
        {
968
            streamSource = new JStreamSource(new DotNetInputStream(input), baseUri.ToString());
969
        }
970

    
971
        /// <summary>
972
        /// The initial mode for the stylesheet. This is either a QName, for a 
973
        /// named mode, or null, for the unnamed (default) mode.
974
        /// </summary>
975

    
976
        public QName InitialMode
977
        {
978
            get
979
            {
980
                JStructuredQName mode = controller.getInitialMode().getModeName();
981
                if (mode == null)
982
                {
983
                    return null;
984
                }
985
                return QName.FromClarkName(mode.getClarkName());
986
            }
987
            set
988
            {
989
                controller.setInitialMode(value.ToStructuredQName());
990
            }
991
        }
992

    
993
        /// <summary>
994
        /// The initial template for the stylesheet. This is either a QName, for a 
995
        /// named template, or null, if no initial template has been set.
996
        /// </summary>
997
        /// <exception cref="DynamicError">Setting this property to the name of a template
998
        /// that does not exist in the stylesheet throws a DynamicError with error 
999
        /// code XTDE0040. Setting it to the name of a template that has template
1000
        /// parameters throws a DynamicError with error code XTDE0060.</exception>
1001

    
1002
        public QName InitialTemplate
1003
        {
1004
            get
1005
            {
1006
                String name = controller.getInitialTemplate().getClarkName();
1007
                if (name == null)
1008
                {
1009
                    return null;
1010
                }
1011
                return QName.FromClarkName(name);
1012
            }
1013
            set
1014
            {
1015
                try
1016
                {
1017
				controller.setInitialTemplate(value.ToStructuredQName());
1018
                }
1019
                catch (javax.xml.transform.TransformerException err)
1020
                {
1021
                    throw new DynamicError(err);
1022
                }
1023
            }
1024
        }
1025

    
1026
	
1027

    
1028
        /// <summary>
1029
        /// The base output URI, which acts as the base URI for resolving the <c>href</c>
1030
        /// attribute of <c>xsl:result-document</c>.
1031
        /// </summary>
1032

    
1033
        public Uri BaseOutputUri
1034
        {
1035
            get
1036
            {
1037
                return new Uri(controller.getBaseOutputURI());
1038
            }
1039
            set
1040
            {
1041
				baseOutputUriWasSet = true;
1042
                controller.setBaseOutputURI(value.ToString());
1043
            }
1044
        }
1045

    
1046
        public RecoveryPolicy RecoveryPolicy
1047
        {
1048
            get
1049
            {
1050
                switch (controller.getRecoveryPolicy())
1051
                {
1052
                    case Configuration.RECOVER_SILENTLY:
1053
                        return RecoveryPolicy.RecoverSilently;
1054
                    case Configuration.RECOVER_WITH_WARNINGS:
1055
                        return RecoveryPolicy.RecoverWithWarnings;
1056
                    default: return RecoveryPolicy.DoNotRecover;
1057
                }
1058
            }
1059
            set
1060
            {
1061
                controller.setRecoveryPolicy(
1062
                    value == RecoveryPolicy.RecoverSilently ? Configuration.RECOVER_SILENTLY :
1063
                    value == RecoveryPolicy.RecoverWithWarnings ? Configuration.RECOVER_WITH_WARNINGS :
1064
                    Configuration.DO_NOT_RECOVER);
1065
            }
1066
        }
1067

    
1068
        /// <summary>
1069
        /// The <c>SchemaValidationMode</c> to be used in this transformation, especially for documents
1070
        /// loaded using the <c>doc()</c>, <c>document()</c>, or <c>collection()</c> functions.
1071
        /// </summary>
1072
        /// 
1073

    
1074
        public SchemaValidationMode SchemaValidationMode
1075
        {
1076
            get
1077
            {
1078
                switch (controller.getSchemaValidationMode())
1079
                {
1080
                    case JValidation.STRICT:
1081
                        return SchemaValidationMode.Strict;
1082
                    case JValidation.LAX:
1083
                        return SchemaValidationMode.Lax;
1084
                    case JValidation.STRIP:
1085
                        return SchemaValidationMode.None;
1086
                    case JValidation.PRESERVE:
1087
                        return SchemaValidationMode.Preserve;
1088
                    case JValidation.DEFAULT:
1089
                    default:
1090
                        return SchemaValidationMode.Unspecified;
1091
                }
1092
            }
1093

    
1094
            set
1095
            {
1096
                switch (value)
1097
                {
1098
                    case SchemaValidationMode.Strict:
1099
                        controller.setSchemaValidationMode(JValidation.STRICT);
1100
                        break;
1101
                    case SchemaValidationMode.Lax:
1102
                        controller.setSchemaValidationMode(JValidation.LAX);
1103
                        break;
1104
                    case SchemaValidationMode.None:
1105
                        controller.setSchemaValidationMode(JValidation.STRIP);
1106
                        break;
1107
                    case SchemaValidationMode.Preserve:
1108
                        controller.setSchemaValidationMode(JValidation.PRESERVE);
1109
                        break;
1110
                    case SchemaValidationMode.Unspecified:
1111
                    default:
1112
                        controller.setSchemaValidationMode(JValidation.DEFAULT);
1113
                        break;
1114
                }
1115
            }
1116
        }
1117

    
1118

    
1119

    
1120

    
1121

    
1122
        /// <summary>
1123
        /// The <c>XmlResolver</c> to be used at run-time to resolve and dereference URIs
1124
        /// supplied to the <c>doc()</c> and <c>document()</c> functions.
1125
        /// </summary>
1126

    
1127
        public XmlResolver InputXmlResolver
1128
        {
1129
            get
1130
            {
1131
                return ((DotNetURIResolver)controller.getURIResolver()).getXmlResolver();
1132
            }
1133
            set
1134
            {
1135
                controller.setURIResolver(new DotNetURIResolver(value));
1136
            }
1137
        }
1138

    
1139
        /// <summary>
1140
        /// The <c>IResultDocumentHandler</c> to be used at run-time to process the output
1141
        /// produced by any <c>xsl:result-document</c> instruction with an <c>href</c>
1142
        /// attribute.
1143
        /// </summary>
1144
        /// <remarks>
1145
        /// In the absence of a user-supplied result document handler, the <c>href</c>
1146
        /// attribute of the <c>xsl:result-document</c> instruction must be a valid relative
1147
        /// URI, which is resolved against the value of the <c>BaseOutputUri</c> property,
1148
        /// and the resulting absolute URI must identify a writable resource (typically
1149
        /// a file in filestore, using the <c>file:</c> URI scheme).
1150
        /// </remarks>
1151

    
1152
        public IResultDocumentHandler ResultDocumentHandler
1153
        {
1154
            get
1155
            {
1156
                return resultDocumentHandler;
1157
            }
1158
            set
1159
            {
1160
                resultDocumentHandler = value;
1161
                controller.setOutputURIResolver(new ResultDocumentHandlerWrapper(value, controller.makePipelineConfiguration()));
1162
            }
1163
        }
1164

    
1165
        /// <summary>
1166
        /// Listener for messages output using &lt;xsl:message&gt;. 
1167
        /// <para>The caller may supply a message listener before calling <c>Run</c>;
1168
        /// the processor will then invoke the listener once for each message generated during
1169
        /// the transformation. Each message will be output as an object of type <c>XdmNode</c>
1170
        /// representing a document node.</para>
1171
        /// <para>If no message listener is supplied by the caller, message information will be written to
1172
        /// the standard error stream.</para>
1173
        /// </summary>
1174
        /// <remarks>
1175
        /// <para>Each message is presented as an XML document node. Calling <c>ToString()</c>
1176
        /// on the message object will usually generate an acceptable representation of the
1177
        /// message.</para>
1178
        /// <para>When the &lt;xsl:message&gt; instruction specifies <c>terminate="yes"</c>,
1179
        /// the message is first notified using this interface, and then an exception is thrown
1180
        /// which terminates the transformation.</para>
1181
        /// </remarks>
1182

    
1183
        public IMessageListener MessageListener
1184
        {
1185
            set
1186
            {
1187
                messageListener = value;
1188
                JPipelineConfiguration pipe = controller.makePipelineConfiguration();
1189
                controller.setMessageEmitter(new MessageListenerProxy(pipe, value));
1190
            }
1191
            get
1192
            {
1193
                return messageListener;
1194
            }
1195
        }
1196

    
1197
        /// <summary>
1198
        /// Destination for output of messages using &lt;trace()&gt;. 
1199
        /// <para>If no message listener is supplied by the caller, message information will be written to
1200
        /// the standard error stream.</para>
1201
        /// </summary>
1202
        /// <remarks>
1203
        /// <para>The supplied destination is ignored if a <c>TraceListener</c> is in use.</para>
1204
		/// <para>Since 9.6. Changed in 9.6 to use a StandardLogger</para>
1205
        /// </remarks>
1206

    
1207
		public StandardLogger TraceFunctionDestination
1208
        {
1209
            set
1210
            {
1211
                traceFunctionDestination = value;
1212
				controller.setTraceFunctionDestination(value);
1213
            }
1214
            get
1215
            {
1216
                return traceFunctionDestination;
1217
            }
1218
        }
1219

    
1220

    
1221

    
1222
        /// <summary>
1223
        /// Set the value of a stylesheet parameter.
1224
        /// </summary>
1225
        /// <param name="name">The name of the parameter, expressed
1226
        /// as a QName. If a parameter of this name has been declared in the
1227
        /// stylesheet, the given value will be assigned to the variable. If the
1228
        /// variable has not been declared, calling this method has no effect (it is
1229
        /// not an error).</param>
1230
        /// <param name="value">The value to be given to the parameter.
1231
        /// If the parameter declaration defines a required type for the variable, then
1232
        /// this value will be converted in the same way as arguments to function calls
1233
        /// (for example, numeric promotion is applied).</param>
1234

    
1235
        public void SetParameter(QName name, XdmValue value)
1236
        {
1237
			staticParameter.put (name.ToStructuredQName(), value.Unwrap());
1238
        }
1239

    
1240

    
1241

    
1242
        /// <summary>
1243
        /// The destination for the results of the stylesheet. The class XmlDestination is an abstraction 
1244
        /// that allows a number of different kinds of destination to be specified.
1245
        /// </summary>
1246
        /// <para>Set the destination to be used for the result of the transformation.</para>
1247
        /// <remarks>
1248
        /// <para>The Destination can be used to chain transformations into a pipeline, by using one
1249
        /// <c>XsltTransformer</c> as the destination of another</para>
1250
        /// </remarks>
1251
        public XmlDestination Destination
1252
        {
1253
            get
1254
            {
1255
                return this.destination;
1256
            }
1257
            set
1258
            {
1259
                this.destination = value;
1260
            }
1261

    
1262
        }
1263

    
1264

    
1265
		/// <summary>
1266
		/// Close the Destination, releasing any resources that need to be released.
1267
		/// </summary>
1268
		/// <remarks>
1269
		/// This method is called by the system on completion of a query or transformation.
1270
		/// Some kinds of Destination may need to close an output stream, others might
1271
		/// not need to do anything. The default implementation does nothing.
1272
		/// </remarks>
1273

    
1274
		public override void Close()
1275
		{
1276
			XdmNode doc = XdmNode;
1277
			if (doc == null) {
1278
				throw new StaticError(new net.sf.saxon.trans.XPathException("No source document has been built by the previous pipeline stage"));
1279
			}
1280

    
1281
			JReceiver result = destination.GetReceiver (controller.makePipelineConfiguration());
1282
			try{
1283
				controller.transform(doc.Implementation, result);
1284
			}catch (javax.xml.transform.TransformerException err)
1285
			{
1286
				throw new DynamicError(err);
1287
			}
1288
			destination.Close();
1289

    
1290
		}
1291

    
1292
		internal JReceiver GetDestinationReceiver(XmlDestination destination){
1293
			if (destination is Serializer) {
1294
				Serializer serializer = (Serializer) destination;
1295
				serializer.SetDefaultOutputProperties(controller.getExecutable ().getDefaultOutputProperties());
1296
				serializer.SetCharacterMap (controller.getExecutable().getCharacterMapIndex());
1297
				String filename = serializer.GetFilename ();
1298
				java.io.OutputStream dest = serializer.GetOutputDestination();
1299
				if (!baseOutputUriWasSet) {
1300
					if (dest is java.io.FileOutputStream) {
1301
						controller.setBaseOutputURI(filename==null ? "" : filename);
1302
					}
1303
				}
1304
				JReceiver r = serializer.GetReceiver(controller.getConfiguration());
1305
				JPipelineConfiguration pipe = r.getPipelineConfiguration();
1306
				pipe.setController(controller);
1307
				pipe.setLocationProvider(controller.getExecutable().getLocationMap());
1308
				return new net.sf.saxon.serialize.ReconfigurableSerializer(r, serializer.GetOutputProperties(), serializer.GetResult(pipe));
1309
			} else {
1310
				JPipelineConfiguration pipe = controller.getConfiguration().makePipelineConfiguration();
1311
				JReceiver r = destination.GetReceiver(pipe);
1312
				pipe.setController(controller);
1313
				pipe.setLocationProvider(controller.getExecutable().getLocationMap());
1314
				return r;
1315
			}
1316
		}
1317

    
1318
        /// <summary>
1319
        /// Run the transformation, sending the result to a specified destination.
1320
        /// </summary>
1321
        /// <param name="destination">
1322
        /// The destination for the results of the stylesheet. The class <c>XmlDestination</c>
1323
        /// is an abstraction that allows a number of different kinds of destination
1324
        /// to be specified.
1325
        /// </param>
1326
        /// <exception cref="DynamicError">Throws a DynamicError if the transformation
1327
        /// fails.</exception>
1328

    
1329
        public void Run(XmlDestination destination)
1330
        {
1331
			if (destination == null) {
1332
				throw new DynamicError ("Destination is null");
1333
			} else {
1334
				this.destination = destination;
1335
				if (destination is Serializer) {
1336
					Serializer serializer = (Serializer)destination;
1337
					serializer.SetDefaultOutputProperties (controller.getExecutable ().getDefaultOutputProperties ());
1338
					serializer.SetCharacterMap (controller.getExecutable ().getCharacterMapIndex ());
1339
				} 
1340
			}
1341
            try
1342
            {
1343
                
1344
				if(staticParameter != null) {
1345
					controller.initializeController(staticParameter);
1346
				}
1347
				if(baseOutputUriWasSet && destination is XdmDestination && 
1348
					((XdmDestination)destination).BaseUri == null && 
1349
				controller.getBaseOutputURI() != null) {
1350
					((XdmDestination)destination).BaseUri = BaseOutputUri;
1351
				}
1352

    
1353
				JPipelineConfiguration pipe = controller.makePipelineConfiguration();
1354
				pipe.setLocationProvider(controller.getExecutable().getLocationMap());
1355

    
1356
                if (streamSource != null)
1357
                {
1358
				controller.transform(streamSource, destination.GetReceiver(pipe));
1359
                }
1360

    
1361
				else if (initialContextNode != null)
1362
                {
1363
                    JDocumentInfo doc = initialContextNode.getDocumentRoot();
1364
                    if (doc != null)
1365
                    {
1366
                        controller.registerDocument(doc, (doc.getBaseURI() == null ? null : new JDocumentURI(doc.getBaseURI())));
1367
                    }
1368
				controller.transform(initialContextNode, destination.GetReceiver(pipe));
1369
                }
1370
                else
1371
                {
1372
                    controller.transform(null, destination.GetReceiver(pipe));
1373
                }
1374

    
1375
                destination.Close();
1376
            }
1377
            catch (javax.xml.transform.TransformerException err)
1378
            {
1379
                throw new DynamicError(err);
1380
            }
1381
        }
1382

    
1383
        /// <summary>
1384
        /// Escape hatch to the underlying Java implementation
1385
        /// </summary>
1386

    
1387
        public Controller Implementation
1388
        {
1389
            get { return controller; }
1390
        }
1391

    
1392

    
1393
    }
1394

    
1395
    /// <summary>
1396
    /// RecoveryPolicy is an enumeration of the different actions that can be taken when a "recoverable error" occurs
1397
    /// </summary>
1398

    
1399
    public enum RecoveryPolicy
1400
    {
1401
        /// <summary>
1402
        /// Ignore the error, take the recovery action, do not produce any message
1403
        /// </summary>
1404
        RecoverSilently,
1405

    
1406
        /// <summary>
1407
        /// Take the recovery action after outputting a warning message
1408
        /// </summary>
1409
        RecoverWithWarnings,
1410

    
1411
        /// <summary>
1412
        /// Treat the error as fatal
1413
        /// </summary>
1414
        DoNotRecover
1415

    
1416
    }
1417

    
1418

    
1419

    
1420
    ///<summary>An <c>IResultDocumentHandler</c> can be nominated to handle output
1421
    /// produced by the <c>xsl:result-document</c> instruction in an XSLT stylesheet.
1422
    ///</summary>
1423
    ///<remarks>
1424
    ///<para>This interface affects any <c>xsl:result-document</c> instruction
1425
    /// executed by the stylesheet, provided that it has an <c>href</c> attribute.</para> 
1426
    ///<para>If no <c>IResultDocumentHandler</c> is nominated (in the
1427
    /// <c>IResultDocumentHandler</c> property of the <c>XsltTransformer</c>), the output
1428
    /// of <code>xsl:result-document</code> is serialized, and is written to the file
1429
    /// or other resource identified by the URI in the <c>href</c> attribute, resolved
1430
    /// (if it is relative) against the URI supplied in the <c>BaseOutputUri</c> property
1431
    /// of the <c>XsltTransformer</c>.</para>
1432
    ///<para>If an <c>IResultDocumentHandler</c> is nominated, however, its
1433
    /// <c>HandleResultDocument</c> method will be called whenever an <c>xsl:result-document</c>
1434
    /// instruction with an <c>href</c> attribute is evaluated, and the generated result tree
1435
    /// will be passed to the <c>XmlDestination</c> returned by that method.</para> 
1436
    ///</remarks>
1437

    
1438
    public interface IResultDocumentHandler
1439
    {
1440

    
1441
        /// <summary> Handle output produced by the <c>xsl:result-document</c>
1442
        /// instruction in an XSLT stylesheet. This method is called by the XSLT processor
1443
        /// when an <c>xsl:result-document</c> with an <c>href</c> attribute is evaluated.
1444
        /// </summary>
1445
        /// <param name="href">An absolute or relative URI. This will be the effective value of the 
1446
        /// <c>href</c> attribute of the <c>xsl:result-document</c> in the stylesheet.</param>
1447
        /// <param name="baseUri">The base URI that should be used for resolving the value of
1448
        /// <c>href</c> if it is relative. This will always be the value of the <c>BaseOutputUri</c>
1449
        /// property of the <c>XsltTransformer</c>.</param>
1450
        /// <returns>An <c>XmlDestination</c> to handle the result tree produced by the
1451
        /// <c>xsl:result-document</c> instruction. The <c>Close</c> method of the returned
1452
        /// <c>XmlDestination</c> will be called when the output is complete.</returns>
1453
        /// <remarks>
1454
        /// <para>The XSLT processor will ensure that the stylesheet cannot create
1455
        /// two distinct result documents which are sent to the same URI. It is the responsibility
1456
        /// of the <c>IResultDocumentHandler</c> to ensure that two distinct result documents are
1457
        /// not sent to the same <c>XmlDestination</c>. Failure to observe this rule can result
1458
        /// in output streams being incorrectly closed.
1459
        /// </para>
1460
        /// <para>Note that more than one result document can be open at the same time,
1461
        /// and that the order of opening, writing, and closing result documents chosen
1462
        /// by the processor does not necessarily bear any direct resemblance to the way
1463
        /// that the XSLT source code is written.</para></remarks>
1464

    
1465
        XmlDestination HandleResultDocument(string href, Uri baseUri);
1466

    
1467
    }
1468

    
1469
	///<summary>Internal wrapper class for <c>IResultDocumentHandler</c></summary>
1470
    internal class ResultDocumentHandlerWrapper : JOutputURIResolver
1471
    {
1472

    
1473
        private IResultDocumentHandler handler;
1474
        private ArrayList resultList = new ArrayList();
1475
        private ArrayList destinationList = new ArrayList();
1476
        private JPipelineConfiguration pipe;
1477

    
1478
		/// <summary>
1479
		/// Initializes a new instance of the <see cref="Saxon.Api.ResultDocumentHandlerWrapper"/> class.
1480
		/// </summary>
1481
		/// <param name="handler">Handler.</param>
1482
		/// <param name="pipe">Pipe.</param>
1483
        public ResultDocumentHandlerWrapper(IResultDocumentHandler handler, JPipelineConfiguration pipe)
1484
        {
1485
            this.handler = handler;
1486
            this.pipe = pipe;
1487
        }
1488

    
1489
		/// <summary>
1490
		/// Create new instance
1491
		/// </summary>
1492
		/// <returns>The <c>JOutURIResolver</c> instance.</returns>
1493
        public JOutputURIResolver newInstance()
1494
        {
1495
            return new ResultDocumentHandlerWrapper(handler, pipe);
1496
        }
1497

    
1498
		/// <summary>
1499
		/// Resolve the specified href and baseString.
1500
		/// </summary>
1501
		/// <param name="href">Href.</param>
1502
		/// <param name="baseString">Base string.</param>
1503
        public JResult resolve(String href, String baseString)
1504
        {
1505
            Uri baseUri;
1506
            try
1507
            {
1508
                baseUri = new Uri(baseString);
1509
            }
1510
            catch (System.UriFormatException err)
1511
            {
1512
                throw new JTransformerException("Invalid base output URI " + baseString, err);
1513
            }
1514
            XmlDestination destination = handler.HandleResultDocument(href, baseUri);
1515
            JResult result = destination.GetReceiver(pipe);
1516
            resultList.Add(result);
1517
            destinationList.Add(destination);
1518
            return result;
1519
        }
1520

    
1521

    
1522
		/// <summary>
1523
		/// Close the specified result.
1524
		/// </summary>
1525
		/// <param name="result">Result.</param>
1526
        public void close(JResult result)
1527
        {
1528
            for (int i = 0; i < resultList.Count; i++)
1529
            {
1530
                if (Object.ReferenceEquals(resultList[i], result))
1531
                {
1532
                    ((XmlDestination)destinationList[i]).Close();
1533
                    resultList.RemoveAt(i);
1534
                    destinationList.RemoveAt(i);
1535
                    return;
1536
                }
1537
            }
1538
        }
1539
    }
1540

    
1541
    ///<summary>An <c>IMessageListener</c> can be nominated to handle output
1542
    /// produced by the <c>xsl:message</c> instruction in an XSLT stylesheet.
1543
    ///</summary>
1544
    ///<remarks>
1545
    ///<para>This interface affects any <c>xsl:message</c> instruction
1546
    /// executed by the stylesheet.</para> 
1547
    ///<para>If no <c>IMessageListener</c> is nominated (in the
1548
    /// <c>MessageListener</c> property of the <c>XsltTransformer</c>), the output
1549
    /// of <code>xsl:message</code> is serialized, and is written to standard error
1550
    /// output stream.</para>
1551
    ///<para>If an <c>IMessageListener</c> is nominated, however, its
1552
    /// <c>Message</c> method will be called whenever an <c>xsl:message</c>
1553
    /// instruction is evaluated.</para> 
1554
    ///</remarks>
1555

    
1556

    
1557
    public interface IMessageListener
1558
    {
1559

    
1560
        ///<summary>Handle the output of an <c>xsl:message</c> instruction
1561
        ///in the stylesheet
1562
        ///</summary>
1563
		///<param name="content"></param>
1564
		/// <param name="terminate"></param>
1565
		/// <param name="location"></param>
1566

    
1567
        void Message(XdmNode content, bool terminate, IXmlLocation location);
1568

    
1569
    }
1570

    
1571
    /// <summary>
1572
    /// An <c>IXmlLocation</c> represents the location of a node within an XML document.
1573
    /// It is in two parts: the base URI (or system ID) of the external entity (which will usually
1574
    /// be the XML document entity itself), and the line number of a node relative
1575
    /// to the base URI of the containing external entity.
1576
    /// </summary>
1577
    /// 
1578

    
1579
    public interface IXmlLocation
1580
    {
1581

    
1582
        /// <summary>
1583
        /// The base URI (system ID) of an external entity within an XML document.
1584
        /// Set to null if the base URI is not known (for example, for an XML document
1585
        /// created programmatically where no base URI has been set up).
1586
        /// </summary>
1587

    
1588
        Uri BaseUri { get; set; }
1589

    
1590
        /// <summary>
1591
        /// The line number of a node relative to the start of the external entity.
1592
        /// The value -1 indicates that the line number is not known or not applicable.
1593
        /// </summary>
1594

    
1595
        int LineNumber { get; set; }
1596
    }
1597

    
1598

    
1599
	/// <summary>
1600
	/// Xml location. An implementation of IXmlLocation
1601
	/// </summary>
1602
    internal class XmlLocation : IXmlLocation
1603
    {
1604
        private Uri baseUri;
1605
        private int lineNumber;
1606
        public Uri BaseUri
1607
        {
1608
            get { return baseUri; }
1609
            set { baseUri = value; }
1610
        }
1611
        public int LineNumber
1612
        {
1613
            get { return lineNumber; }
1614
            set { lineNumber = value; }
1615
        }
1616
    }
1617

    
1618

    
1619
	/// <summary>
1620
	/// Message listener proxy. This class implements a Receiver that can receive xsl:message output and send it to a
1621
	/// user-supplied MessageListener
1622
	/// </summary>
1623
    [Serializable]
1624
    internal class MessageListenerProxy : JSequenceWriter
1625
    {
1626

    
1627
        public IMessageListener listener;
1628
        public bool terminate;
1629
        public int locationId;
1630

    
1631
		/// <summary>
1632
		/// Initializes a new instance of the <see cref="Saxon.Api.MessageListenerProxy"/> class.
1633
		/// </summary>
1634
		/// <param name="pipe">pipe.</param>
1635
		/// <param name="ml">ml.</param>
1636
        public MessageListenerProxy(JPipelineConfiguration pipe, IMessageListener ml)
1637
            : base(pipe)
1638
        {
1639
            listener = ml;
1640
            base.setTreeModel(net.sf.saxon.om.TreeModel.LINKED_TREE);
1641
        }
1642

    
1643

    
1644
		/// <summary>
1645
		/// Starts the document.
1646
		/// </summary>
1647
		/// <param name="properties">Properties.</param>
1648
        public override void startDocument(int properties)
1649
        {
1650
            terminate = (properties & JReceiverOptions.TERMINATE) != 0;
1651
            locationId = -1;
1652
            base.startDocument(properties);
1653
        }
1654

    
1655

    
1656
		/// <summary>
1657
		/// Starts the element.
1658
		/// </summary>
1659
		/// <param name="nameCode">Name code.</param>
1660
		/// <param name="typeCode">Type code.</param>
1661
		/// <param name="locationId">Location identifier.</param>
1662
		/// <param name="properties">Properties.</param>
1663
        public override void startElement(JNodeName nameCode, JSchemaType typeCode, int locationId, int properties)
1664
        {
1665
            if (this.locationId == -1)
1666
            {
1667
                this.locationId = locationId;
1668
            }
1669
            base.startElement(nameCode, typeCode, locationId, properties);
1670
        }
1671

    
1672
		/// <summary>
1673
		/// Characters the specified s, locationId and properties.
1674
		/// </summary>
1675
		/// <param name="s">S.</param>
1676
		/// <param name="locationId">Location identifier.</param>
1677
		/// <param name="properties">Properties.</param>
1678
        public override void characters(CharSequence s, int locationId, int properties)
1679
        {
1680
            if (this.locationId == -1)
1681
            {
1682
                this.locationId = locationId;
1683
            }
1684
            base.characters(s, locationId, properties);
1685
        }
1686

    
1687

    
1688
		/// <summary>
1689
		/// Append the specified item, locationId and copyNamespaces.
1690
		/// </summary>
1691
		/// <param name="item">Item.</param>
1692
		/// <param name="locationId">Location identifier.</param>
1693
		/// <param name="copyNamespaces">Copy namespaces.</param>
1694
        public override void append(JItem item, int locationId, int copyNamespaces)
1695
        {
1696
            if (this.locationId == -1)
1697
            {
1698
                this.locationId = locationId;
1699
            }
1700
            base.append(item, locationId, copyNamespaces);
1701
        }
1702

    
1703

    
1704
		/// <summary>
1705
		/// Write the specified item.
1706
		/// </summary>
1707
		/// <param name="item">Item.</param>
1708
        public override void write(JItem item)
1709
        {
1710
            XmlLocation loc = new XmlLocation();
1711
            if (locationId != -1)
1712
            {
1713
                JLocationProvider provider = getPipelineConfiguration().getLocationProvider();
1714
                loc.BaseUri = new Uri(provider.getSystemId(locationId));
1715
                loc.LineNumber = provider.getLineNumber(locationId);
1716
            }
1717
            listener.Message((XdmNode)XdmItem.Wrap(item), terminate, loc);
1718
        }
1719
    }
1720

    
1721

    
1722

    
1723
 	/// <summary>An <code>Xslt30Transformer</code> represents a compiled and loaded stylesheet ready for execution.
1724
	/// The <code>Xslt30Transformer</code> holds details of the dynamic evaluation context for the stylesheet.</summary>
1725
 
1726
	///<remarks><para>The <code>Xslt30Transformer</code> differs from {@link XsltTransformer} is supporting new options
1727
 	/// for invoking a stylesheet, corresponding to facilities defined in the XSLT 3.0 specification. However,
1728
 	/// it is not confined to use with XSLT 3.0, and most of the new invocation facilities (for example,
1729
    /// calling a stylesheet-defined function directly) work equally well with XSLT 2.0 and in some cases
1730
    /// XSLT 1.0 stylesheets.</para>
1731
 	/// <para>An <code>Xslt30Transformer</code> must not be used concurrently in multiple threads.
1732
 	/// It is safe, however, to reuse the object within a single thread to run the same
1733
 	/// stylesheet several times. Running the stylesheet does not change the context
1734
 	/// that has been established.</para>
1735
 
1736
 	/// <para>An <code>Xslt30Transformer</code> is always constructed by running the <code>Load30</code>
1737
 	/// method of an {@link XsltExecutable}.</para>
1738
 
1739
 	/// <para>Unlike <code>XsltTransformer</code>, an <code>Xslt30Transformer</code> is not a <code>Destination</code>. T
1740
 	/// To pipe the results of one transformation into another, the target should be an <code>XsltTransfomer</code>
1741
 	/// rather than an <code>Xslt30Transformer</code>.</para>
1742

    
1743
 	/// <para>Evaluation of an Xslt30Transformer proceeds in a number of phases:</para>
1744
 	///<list type="number">
1745
 	/// <item><term>First<term><description> values may be supplied for stylesheet parameters and for the global context item. The
1746
 	/// global context item is used when initializing global variables. Unlike earlier transformation APIs,
1747
 	/// the global context item is quite independent of the "principal Source document".
1748
 	/// </item>
1749
 	/// <item><term>stylesheet<term> may now be repeatedly invoked. Each invocation takes one of three forms:
1750
 	/// <list type="bullet">
1751
 	/// <item>Invocation by applying templates. In this case, the information required is (i) an initial
1752
 	/// mode (which defaults to the unnamed mode), (ii) an initial match sequence, which is any
1753
 	/// XDM value, which is used as the effective "select" expression of the implicit apply-templates
1754
 	/// call, and (iii) optionally, values for the tunnel and non-tunnel parameters defined on the
1755
 	/// templates that get invoked (equivalent to using <code>xsl:with-param</code> on the implicit
1756
 	/// <code>apply-templates</code> call).</item>
1757
 	/// <item>Invocation by calling a named template. In this case, the information required is
1758
 	/// (i) the name of the initial template (which defaults to "xsl:initial-template"), and
1759
 	/// (ii) optionally, values for the tunnel and non-tunnel parameters defined on the
1760
 	/// templates that get invoked (equivalent to using <code>xsl:with-param</code> on the implicit
1761
 	/// <code>call-template</code> instruction).</item>
1762
 	/// <item>Invocation by calling a named function. In this case, the information required is
1763
 	/// the sequence of arguments to the function call.</item>
1764
 	/// </list>
1765
 	/// </item>
1766
 	/// <item><description>Whichever invocation method is chosen, the result may either be returned directly, as an arbitrary
1767
 	/// XDM value, or it may effectively be wrapped in an XML document. If it is wrapped in an XML document,
1768
 	/// that document can be processed in a number of ways, for example it can be materialized as a tree in
1769
 	/// memory, it can be serialized as XML or HTML, or it can be subjected to further transformation.</description></item>
1770
 	/// </list>
1771
 	/// <<para>Once the stylesheet has been invoked (using any of these methods), the values of the global context
1772
 	/// item and stylesheet parameters cannot be changed. If it is necessary to run another transformation with
1773
 	/// a different context item or different stylesheet parameters, a new <c>Xslt30Transformer</c>
1774
 	/// should be created from the original <c>XsltExecutable</c>.</para>
1775
	/// <para> @since 9.6</para> 
1776
	/// </remark>
1777

    
1778
    [Serializable]
1779
    public class Xslt30Transformer
1780
    {
1781

    
1782
	private Controller controller;
1783
	private GlobalParameterSet globalParameterSet;
1784
	private bool primed;
1785
	private bool baseOutputUriWasSet;
1786
	private IMessageListener messageListener;
1787
	private StandardLogger traceFunctionDestination;
1788
	private JStreamSource streamSource;
1789
	private Processor processor;
1790

    
1791

    
1792
	internal Xslt30Transformer(Processor proc, Controller controller, GlobalParameterSet staticParameter)
1793
        {
1794

    
1795
			this.controller = controller;
1796
			this.processor = proc;
1797
			this.globalParameterSet = new GlobalParameterSet(staticParameter);
1798
        }
1799

    
1800
	
1801
     ///<summary> Supply the context item to be used when evaluating global variables and parameters.
1802
     /// The item to be used as the context item within the initializers
1803
     /// of global variables and parameters. This argument can be null if no context item is to be
1804
	///  supplied.</summary>
1805
    public XdmItem GlobalContextItem
1806
        {
1807
		set { 
1808
				if (primed) {
1809
					throw new DynamicError("Stylesheet has already been evaluated");
1810
				}
1811
			controller.setInitialContextItem(value==null ? null : value.value.head());
1812
		}
1813
		get { return (XdmItem)XdmItem.Wrap(controller.getInitialContextItem()); }
1814

    
1815
    }
1816

    
1817

    
1818
	///<summary> Get the underlying Controller used to implement this XsltTransformer. This provides access
1819
    /// to lower-level methods not otherwise available in the s9api interface. Note that classes
1820
	/// and methods obtained by this route cannot be guaranteed stable from release to release.</summary>
1821
	///<returns> The underlying {@link Controller}</returns>
1822
	public Controller GetUnderlyingController {
1823
		get { return controller; }
1824
	}
1825

    
1826
	internal JReceiver GetDestinationReceiver(XmlDestination destination){
1827
		if (destination is Serializer) {
1828
			Serializer serializer = (Serializer) destination;
1829
			serializer.SetDefaultOutputProperties(controller.getExecutable ().getDefaultOutputProperties());
1830
			serializer.SetCharacterMap (controller.getExecutable().getCharacterMapIndex());
1831
			String filename = serializer.GetFilename ();
1832
			java.io.OutputStream dest = serializer.GetOutputDestination();
1833
			if (!baseOutputUriWasSet) {
1834
				if (dest is java.io.FileOutputStream) {
1835
					controller.setBaseOutputURI(filename==null ? "" : filename);
1836
				}
1837
			}
1838
			JReceiver r = serializer.GetReceiver(controller.getConfiguration());
1839
			JPipelineConfiguration pipe = r.getPipelineConfiguration();
1840
			pipe.setController(controller);
1841
			pipe.setLocationProvider(controller.getExecutable().getLocationMap());
1842
			return new net.sf.saxon.serialize.ReconfigurableSerializer(r, serializer.GetOutputProperties(), serializer.GetResult(pipe));
1843
		} else {
1844
			JPipelineConfiguration pipe = controller.getConfiguration().makePipelineConfiguration();
1845
			JReceiver r = destination.GetReceiver(pipe);
1846
			pipe.setController(controller);
1847
			pipe.setLocationProvider(controller.getExecutable().getLocationMap());
1848
			return r;
1849
		}
1850
	}
1851

    
1852
	/// <summary>
1853
	/// The <c>SchemaValidationMode</c> to be used in this transformation, especially for documents
1854
	/// loaded using the <code>doc()</code>, <code>document()</code>, or <code>collection()</code> functions.
1855
	/// </summary>
1856
	/// 
1857

    
1858
	public SchemaValidationMode SchemaValidationMode
1859
	{
1860
		get
1861
		{
1862
			switch (controller.getSchemaValidationMode())
1863
			{
1864
			case JValidation.STRICT:
1865
				return SchemaValidationMode.Strict;
1866
			case JValidation.LAX:
1867
				return SchemaValidationMode.Lax;
1868
			case JValidation.STRIP:
1869
				return SchemaValidationMode.None;
1870
			case JValidation.PRESERVE:
1871
				return SchemaValidationMode.Preserve;
1872
			case JValidation.DEFAULT:
1873
			default:
1874
				return SchemaValidationMode.Unspecified;
1875
			}
1876
		}
1877

    
1878

    
1879
		set
1880
		{
1881
			switch (value)
1882
			{
1883
			case SchemaValidationMode.Strict:
1884
				controller.setSchemaValidationMode(JValidation.STRICT);
1885
				break;
1886
			case SchemaValidationMode.Lax:
1887
				controller.setSchemaValidationMode(JValidation.LAX);
1888
				break;
1889
			case SchemaValidationMode.None:
1890
				controller.setSchemaValidationMode(JValidation.STRIP);
1891
				break;
1892
			case SchemaValidationMode.Preserve:
1893
				controller.setSchemaValidationMode(JValidation.PRESERVE);
1894
				break;
1895
			case SchemaValidationMode.Unspecified:
1896
			default:
1897
				controller.setSchemaValidationMode(JValidation.DEFAULT);
1898
				break;
1899
			}
1900
		}
1901
	}
1902

    
1903

    
1904

    
1905
	///<summary> Supply the values of global stylesheet variables and parameters.</summary>
1906
	/// <param> parameters a map whose keys are QNames identifying global stylesheet parameters,
1907
	/// and whose corresponding values are the values to be assigned to those parameters. If necessary
1908
	/// the supplied values are converted to the declared type of the parameter.
1909
	/// The contents of the supplied map are copied by this method,
1910
	/// so subsequent changes to the map have no effect.
1911
	/// </param>
1912
	/// <param name="parameters">Parameters. A Dictionary whose keys are QNames identifying global stylesheet parameters,
1913
	///and whose corresponding values are the values to be assigned to those parameters. If necessary
1914
	///the supplied values are converted to the declared type of the parameter.
1915
	///The contents of the supplied map are copied by this method,
1916
	///so subsequent changes to the map have no effect.</param>
1917
	public void SetStylesheetParameters(Dictionary<QName, XdmValue> parameters){
1918

    
1919
		if (primed) {
1920
			throw new DynamicError("Stylesheet has already been evaluated");
1921
		}
1922
		//try {
1923
		GlobalParameterSet params1 = new GlobalParameterSet();
1924
		foreach (KeyValuePair<QName, XdmValue> entry in parameters) {
1925
			QName qname = entry.Key;
1926
			params1.put (qname.ToStructuredQName(), entry.Value.value);
1927
		}
1928
	
1929
		globalParameterSet = params1;
1930
	
1931
	
1932
	}
1933

    
1934

    
1935
	internal void prime() {
1936
		if (!primed) {
1937
			if (globalParameterSet == null) {
1938
				globalParameterSet = new GlobalParameterSet();
1939
			}
1940
			try {
1941
				controller.initializeController(globalParameterSet);
1942
			} catch (net.sf.saxon.trans.XPathException e) {
1943
				throw new DynamicError(e);
1944
			}
1945
		}
1946
		primed = true;
1947
	}
1948

    
1949

    
1950
	
1951
	 /// <summary> Get the base output URI.</summary>
1952
	 /// <remarks><para> This returns the value set using the {@link #setBaseOutputURI} method. If no value has been set
1953
     /// explicitly, then the method returns null if called before the transformation, or the computed
1954
     /// default base output URI if called after the transformation.</p>
1955
     /// </para>
1956
     /// <para> The base output URI is used for resolving relative URIs in the <code>href</code> attribute
1957
     /// of the <code>xsl:result-document</code> instruction.</para>
1958
	 /// <returns> The base output URI</returns>
1959
     
1960
	public String BaseOutputURI {
1961
		set {
1962
		controller.setBaseOutputURI(value);
1963
			baseOutputUriWasSet = value != null;
1964
		}
1965
		get { return controller.getBaseOutputURI ();}
1966
	}
1967

    
1968
	/// <summary>
1969
	/// The <c>XmlResolver</c> to be used at run-time to resolve and dereference URIs
1970
	/// supplied to the <c>doc()</c> and <c>document()</c> functions.
1971
	/// </summary>
1972

    
1973
	public XmlResolver InputXmlResolver
1974
	{
1975
		get
1976
		{
1977
			return ((DotNetURIResolver)controller.getURIResolver()).getXmlResolver();
1978
		}
1979
		set
1980
		{
1981
			controller.setURIResolver(new DotNetURIResolver(value));
1982
		}
1983
	}
1984
		
1985

    
1986
	/// <summary>
1987
	/// Listener for messages output using &lt;xsl:message&gt;. 
1988
	/// <para>The caller may supply a message listener before calling <c>Run</c>;
1989
	/// the processor will then invoke the listener once for each message generated during
1990
	/// the transformation. Each message will be output as an object of type <c>XdmNode</c>
1991
	/// representing a document node.</para>
1992
	/// <para>If no message listener is supplied by the caller, message information will be written to
1993
	/// the standard error stream.</para>
1994
	/// </summary>
1995
	/// <remarks>
1996
	/// <para>Each message is presented as an XML document node. Calling <c>ToString()</c>
1997
	/// on the message object will usually generate an acceptable representation of the
1998
	/// message.</para>
1999
	/// <para>When the &lt;xsl:message&gt; instruction specifies <c>terminate="yes"</c>,
2000
	/// the message is first notified using this interface, and then an exception is thrown
2001
	/// which terminates the transformation.</para>
2002
	/// </remarks>
2003

    
2004
	public IMessageListener MessageListener
2005
	{
2006
		set
2007
		{
2008
			messageListener = value;
2009
			JPipelineConfiguration pipe = controller.makePipelineConfiguration();
2010
			controller.setMessageEmitter(new MessageListenerProxy(pipe, value));
2011
		}
2012
		get
2013
		{
2014
			return messageListener;
2015
		}
2016
	}
2017

    
2018
	/// <summary>
2019
	/// Destination for output of messages using &lt;trace()&gt;. 
2020
	/// <para>If no message listener is supplied by the caller, message information will be written to
2021
	/// the standard error stream.</para>
2022
	/// </summary>
2023
	/// <remarks>
2024
	/// <para>The supplied destination is ignored if a <code>TraceListener</code> is in use.</para>
2025
	/// <para>Since 9.6. Changed in 9.6 to use a StandardLogger</para>
2026
	/// </remarks>
2027

    
2028
	public StandardLogger TraceFunctionDestination
2029
	{
2030
		set
2031
		{
2032
			traceFunctionDestination = value;
2033
			controller.setTraceFunctionDestination(value);
2034
		}
2035
		get
2036
		{
2037
			return traceFunctionDestination;
2038
		}
2039
	}
2040

    
2041

    
2042
     ///<summary><para> Set parameters to be passed to the initial template. These are used
2043
     /// whether the transformation is invoked by applying templates to an initial source item,
2044
     /// or by invoking a named template. The parameters in question are the xsl:param elements
2045
     /// appearing as children of the xsl:template element. </para>
2046
 	/// <remarks>
2047
     /// <para>The parameters are supplied in the form of a map; the key is a QName which must
2048
     /// match the name of the parameter; the associated value is an XdmValue containing the
2049
     /// value to be used for the parameter. If the initial template defines any required
2050
     /// parameters, the map must include a corresponding value. If the initial template defines
2051
     /// any parameters that are not present in the map, the default value is used. If the map
2052
     /// contains any parameters that are not defined in the initial template, these values
2053
     /// are silently ignored.</para>
2054
    
2055
     /// <para>The supplied values are converted to the required type using the function conversion
2056
     /// rules. If conversion is not possible, a run-time error occurs (not now, but later, when
2057
     /// the transformation is actually run).</para>
2058
     /// <para>The <code>XsltTransformer</code> retains a reference to the supplied map, so parameters can be added or
2059
     /// changed until the point where the transformation is run.</para>
2060
     /// <para>The XSLT 3.0 specification makes provision for supplying parameters to the initial
2061
     /// template, as well as global stylesheet parameters. Although there is no similar provision
2062
     /// in the XSLT 1.0 or 2.0 specifications, this method works for all stylesheets, regardless whether
2063
     /// XSLT 3.0 is enabled or not.</para></remarks>
2064
     
2065
	 ///<param name="parameters"> The parameters to be used for the initial template</param>
2066
	 ///<param name="tunnel"> true if these values are to be used for setting tunnel parameters;
2067
	 ///false if they are to be used for non-tunnel parameters</param>
2068
     
2069
	public void SetInitialTemplateParameters(Dictionary<QName, XdmValue> parameters, bool tunnel){
2070
	
2071
		JMap templateParameters = new java.util.HashMap ();
2072
		foreach (KeyValuePair<QName, XdmValue> entry in parameters) {
2073
			QName qname = entry.Key;
2074
			templateParameters.put (qname.ToStructuredQName(), entry.Value.value);
2075
		}
2076

    
2077
		controller.setInitialTemplateParameters (templateParameters, tunnel);
2078

    
2079
	
2080
	}
2081

    
2082

    
2083
	/// <summary>initial mode for the transformation. This is used if the stylesheet is
2084
	/// subsequently invoked by any of the <code>applyTemplates</code> methods.</summary>
2085
	///<remarks><para>The value may be the name of the initial mode, or null to indicate the default
2086
	/// (unnamed) mode</para></remarks>
2087

    
2088
	public QName InitialMode {
2089

    
2090
		set {
2091
			try {
2092
				controller.setInitialMode(value == null ? null : value.ToStructuredQName());
2093
			} catch (net.sf.saxon.trans.XPathException e) {
2094
				throw new DynamicError(e);
2095
			}
2096
		}
2097
		get{
2098
				net.sf.saxon.trans.Mode mode = controller.getInitialMode ();
2099
				if (mode == null)
2100
					return null;
2101
				else
2102
				return new QName (mode.getModeName().ToString());
2103
		}
2104

    
2105
	
2106
	}
2107

    
2108

    
2109
	/// <summary>Invoke the stylesheet by applying templates to a supplied Source document, sending the results (wrapped
2110
	/// in a document node) to a given Destination. The invocation uses any initial mode set using {@link #setInitialMode(QName)},
2111
	/// and any template parameters set using {@link #setInitialTemplateParameters(java.util.Map, boolean)}.
2112
	/// </summary>
2113
	/// <param name="input">Input. The source document.To apply more than one transformation to the same source document, the source document
2114
	/// tree can be pre-built using a {@link DocumentBuilder}.</param>
2115
	/// <param name="destination">Destination. the destination of the result document produced by wrapping the result of the apply-templates
2116
	/// call in a document node.  If the destination is a {@link Serializer}, then the serialization
2117
	/// parameters set in the serializer are combined with those defined in the stylesheet
2118
	/// (the parameters set in the serializer take precedence).</param>
2119
	public void ApplyTemplates(Stream input, XmlDestination destination){
2120
		prime ();
2121
		streamSource = new JStreamSource(new DotNetInputStream(input));
2122

    
2123
		try{
2124
			JReceiver outi = GetDestinationReceiver(destination);// destination.GetReceiver(controller.makePipelineConfiguration());
2125
			controller.initializeController (globalParameterSet);
2126
			controller.transform (streamSource, outi);
2127
		} catch(net.sf.saxon.trans.XPathException exp){
2128
			throw new DynamicError(exp);
2129
		}
2130
	
2131
	}
2132

    
2133
	/// <summary>
2134
	/// Invoke the stylesheet by applying templates to a supplied Source document, returning the raw results
2135
	/// as an {@link XdmValue}. The invocation uses any initial mode set using {@link #setInitialMode(QName)},
2136
	/// and any template parameters set using {@link #setInitialTemplateParameters(java.util.Map, boolean)}.
2137
	/// </summary>
2138
	/// <param name="input">Input. The source document</param>
2139
	/// <param name="baseUri">Base URI.</param>
2140
	/// <returns>XdmValue. The raw result of processing the supplied Source using the selected template rule, without
2141
	/// wrapping the returned sequence in a document node</returns>
2142
	public XdmValue ApplyTemplates(Stream input, Uri baseUri){
2143
		prime ();
2144
		streamSource = new JStreamSource(new DotNetInputStream(input), baseUri.ToString());
2145

    
2146
		try{
2147
			JPipelineConfiguration pipe = controller.makePipelineConfiguration();
2148
			JSequenceOutputter outi = new JSequenceOutputter(pipe, controller, 1);
2149
			controller.initializeController(globalParameterSet);
2150
			controller.transform(streamSource, outi);
2151

    
2152

    
2153
			controller.initializeController (globalParameterSet);
2154
			controller.transform (streamSource, outi);
2155
			return XdmValue.Wrap(outi.getSequence());
2156
		} catch(net.sf.saxon.trans.XPathException exp){
2157
			throw new DynamicError(exp);
2158
		}
2159

    
2160
	}
2161

    
2162

    
2163
	/// <summary>
2164
	/// Invoke the stylesheet by applying templates to a supplied input sequence, sending the results (wrapped
2165
	/// in a document node) to a given Destination. The invocation uses any initial mode set using {@link #setInitialMode(QName)},
2166
	/// and any template parameters set using {@link #setInitialTemplateParameters(java.util.Map, boolean)}.
2167
	/// </summary>
2168
	/// <param name="selection">Selection. the initial value to which templates are to be applied (equivalent to the <code>select</code>
2169
	/// attribute of <code>xsl:apply-templates</code>)</param>
2170
	/// <param name="destination">Destination. The destination of the result document produced by wrapping the result of the apply-templates
2171
	/// call in a document node.  If the destination is a {@link Serializer}, then the serialization
2172
	/// parameters set in the serializer are combined with those defined in the stylesheet
2173
	/// (the parameters set in the serializer take precedence).</param>
2174
	public void ApplyTemplates(XdmValue selection, XmlDestination destination){
2175
		prime ();
2176
		try{
2177
			JReceiver outi = GetDestinationReceiver(destination);
2178
			if(baseOutputUriWasSet) {
2179
				outi.setSystemId(controller.getBaseOutputURI());
2180
			}
2181
			controller.applyTemplates(selection.Unwrap(), outi);
2182
			destination.Close();
2183
		}catch(net.sf.saxon.trans.XPathException ex){
2184

    
2185
				throw new DynamicError (ex);
2186
		}
2187
	
2188
	}
2189

    
2190

    
2191
	/// <summary>
2192
	/// Invoke the stylesheet by applying templates to a supplied input sequence, returning the raw results.
2193
	/// as an {@link XdmValue}. The invocation uses any initial mode set using {@link #setInitialMode(QName)},
2194
	/// and any template parameters set using {@link #setInitialTemplateParameters(java.util.Map, boolean)}.
2195
	/// </summary>
2196
	/// <param name="selection">Selection. selection the initial value to which templates are to be applied (equivalent to the <code>select</code>
2197
	/// attribute of <code>xsl:apply-templates</code>)</param>
2198
	/// <returns>Xdmvalue. he raw result of applying templates to the supplied selection value, without wrapping in
2199
	/// a document node or serializing the result. If there is more that one item in the selection, the result
2200
	/// is the concatenation of the results of applying templates to each item in turn.</returns>
2201
	public XdmValue ApplyTemplates(XdmValue selection){
2202
		prime ();
2203
		try{
2204

    
2205
			JPipelineConfiguration pipe = controller.makePipelineConfiguration();
2206
			JSequenceOutputter outi = new JSequenceOutputter(pipe, controller, 1);
2207

    
2208
			if(baseOutputUriWasSet) {
2209
				outi.setSystemId(controller.getBaseOutputURI());
2210
			}
2211
			controller.applyTemplates(selection.Unwrap(), outi);
2212
			return XdmValue.Wrap(outi.getSequence());
2213
		}catch(net.sf.saxon.trans.XPathException ex){
2214

    
2215
			throw new DynamicError (ex);
2216
		}
2217

    
2218
	}
2219

    
2220

    
2221
     ///<summary> Invoke a transformation by calling a named template. The results of calling
2222
     /// the template are wrapped in a document node, which is then sent to the specified
2223
     /// destination. If {@link #setInitialTemplateParameters(java.util.Map, boolean)} has been
2224
    /// called, then the parameters supplied are made available to the called template (no error
2225
	/// occurs if parameters are supplied that are not used).</summary> 
2226
	///<param name="templateName"> The name of the initial template. This must match the name of a
2227
    /// public named template in the stylesheet. If the value is null,
2228
	/// the QName <code>xsl:initial-template</code> is used.</param>
2229
	/// <param name="destination"> The destination of the result document produced by wrapping the result of the apply-templates
2230
    /// call in a document node.  If the destination is a {@link Serializer}, then the serialization
2231
    /// parameters set in the serializer are combined with those defined in the stylesheet
2232
	/// (the parameters set in the serializer take precedence).</param> 
2233
	public void CallTemplate(QName templateName, XmlDestination destination){
2234
		prime ();
2235
		if (templateName == null) {
2236
			templateName = new QName ("xsl", NamespaceConstant.XSLT, "initial-template");
2237
		}
2238
		/*if (destination is Serializer) {
2239
			Serializer serializer = (Serializer)destination;
2240
			serializer.SetDefaultOutputProperties(controller.getExecutable ().getDefaultOutputProperties());
2241

    
2242
		}*/
2243
		try{
2244
			JReceiver outi = GetDestinationReceiver(destination);
2245
			if(baseOutputUriWasSet) {
2246
				outi.setSystemId(controller.getBaseOutputURI());
2247
			}
2248
			controller.callTemplate(templateName.ToStructuredQName(), outi);
2249
		} catch(net.sf.saxon.trans.XPathException exp){
2250
			throw new DynamicError(exp);
2251
		}
2252
	}
2253

    
2254

    
2255

    
2256

    
2257
	public XdmValue CallTemplate(QName templateName){
2258
		prime ();
2259
		if (templateName == null) {
2260
			templateName = new QName ("xsl", NamespaceConstant.XSLT, "initial-template");
2261
		}
2262

    
2263
		try{
2264
			JPipelineConfiguration pipe = controller.makePipelineConfiguration();
2265
			JSequenceOutputter outi = new JSequenceOutputter(pipe, controller, 1);
2266

    
2267
			controller.callTemplate(templateName.ToStructuredQName(), outi);
2268
			return XdmValue.Wrap(outi.getSequence());
2269
		} catch(net.sf.saxon.trans.XPathException exp){
2270
			throw new DynamicError(exp);
2271
		}
2272
	}
2273

    
2274

    
2275
     ///<summary> Call a public user-defined function in the stylesheet. </summary>
2276
	 /// <param name="function"> The name of the function to be called</param>
2277
	 ///<param name="argument">  The values of the arguments to be supplied to the function. These
2278
     /// will be converted if necessary to the type as defined in the function signature, using
2279
	 /// the function conversion rules.</param>
2280
	/// <returns> the result of calling the function. This is the raw result, without wrapping in a document
2281
	/// node and without serialization.</returns>
2282

    
2283
	public XdmValue CallFunction(QName function, XdmValue[] arguments){
2284
		prime ();
2285
		try{
2286
		net.sf.saxon.trans.SymbolicName fName = new net.sf.saxon.trans.SymbolicName(net.sf.saxon.om.StandardNames.XSL_FUNCTION, function.ToStructuredQName(), arguments.Length);
2287
			JConfiguration config = processor.Implementation;
2288
		net.sf.saxon.sxpath.IndependentContext env = new net.sf.saxon.sxpath.IndependentContext(config);
2289
		PreparedStylesheet pss = (PreparedStylesheet) controller.getExecutable();
2290
		net.sf.saxon.expr.Component f = pss.getComponent(fName);
2291
		if (f == null) {
2292
				net.sf.saxon.trans.XPathException exception = new net.sf.saxon.trans.XPathException ("No function with name " + function.ClarkName + " and arity " + arguments.Length + " has been declared in the stylesheet", "XTDE0041");
2293
				throw new DynamicError(exception);
2294
		}
2295
		JUserFunction uf = (JUserFunction)f.getProcedure ();
2296
		net.sf.saxon.expr.instruct.UserFunctionParameter [] params1 = uf.getParameterDefinitions();
2297
		net.sf.saxon.om.Sequence [] vr = new net.sf.saxon.om.Sequence[arguments.Length];
2298
		for (int i = 0; i < arguments.Length; i++) {
2299
			net.sf.saxon.value.SequenceType type = params1[i].getRequiredType();
2300
				vr [i] = arguments [i].Unwrap ();
2301
			if (!type.matches(vr[i], config)) {
2302
				JRoleLocator role = new JRoleLocator(JRoleLocator.FUNCTION, function.ToStructuredQName(), i);
2303
				vr[i] = config.getTypeHierarchy().applyFunctionConversionRules(vr[i], type, role, env);
2304
			}
2305
		}
2306

    
2307
		net.sf.saxon.expr.XPathContextMajor context = controller.newXPathContext ();
2308
		context.setCurrentComponent (pss.getComponent(fName));
2309
		net.sf.saxon.om.Sequence result = uf.call (context, vr);
2310
		return XdmValue.Wrap (result);
2311
		} catch(net.sf.saxon.trans.XPathException ex){
2312
			throw new DynamicError(ex);
2313

    
2314
		}
2315
	
2316
	}
2317

    
2318

    
2319
	
2320
    /// <summary>Call a public user-defined function in the stylesheet, wrapping the result in an XML document, and sending
2321
    /// this document to a specified destination</summary>    
2322
	///<param name="function"> The name of the function to be called</param>
2323
	///<param name="arguments"> The values of the arguments to be supplied to the function. These
2324
    ///                    will be converted if necessary to the type as defined in the function signature, using
2325
	///                    the function conversion rules.</param>
2326
	///<param name="destination"> The destination of the result document produced by wrapping the result of the apply-templates
2327
    ///                    call in a document node.  If the destination is a {@link Serializer}, then the serialization
2328
    ///                    parameters set in the serializer are combined with those defined in the stylesheet
2329
	//                    (the parameters set in the serializer take precedence).</param>
2330
     
2331
	public void CallFunction(QName function, XdmValue[] arguments, XmlDestination destination){
2332
		XdmValue result = CallFunction (function, arguments);
2333
		if (destination is Serializer) {
2334
			// TODO: call the function in push mode, avoiding creation of the result in memory
2335
			Serializer serializer = (Serializer) destination;
2336
			serializer.SetDefaultOutputProperties(controller.getExecutable().getDefaultOutputProperties());
2337
			processor.WriteXdmValue (result, destination);
2338
			destination.Close ();
2339
		}
2340

    
2341
	
2342
	}
2343

    
2344

    
2345

    
2346

    
2347
    }
2348

    
2349
	///<summary> An <c>XsltPackage</c> object represents the result of compiling an XSLT 3.0 package, as
2350
 	/// represented by an XML document containing an <c>xsl:package</c> element.</summary>
2351
	/// <remarks><para>
2352
	/// @since 9.6
2353
	/// </para></remarks>
2354

    
2355
[Serializable]
2356
public class XsltPackage
2357
{
2358
	private Processor processor;
2359
	private JXsltPackage package;
2360

    
2361
	/// <summary>
2362
	/// Initializes a new instance of the <see cref="Saxon.Api.XsltPackage"/> class.
2363
	/// </summary>
2364
	/// <param name="p">Processor</param>
2365
	/// <param name="pp">XsltPackage</param>
2366
	internal XsltPackage(Processor p, JXsltPackage pp){
2367
		this.processor = p;
2368
		this.package = pp;
2369

    
2370
	}
2371

    
2372
	/// <summary>
2373
	/// Get the Processor from which this XsltCompiler was constructed
2374
	/// </summary>
2375
	public Processor Processor
2376
	{
2377
		get { return processor; }
2378
	}
2379

    
2380
	/**
2381
	 * <summary>
2382
     * Get the name of the package (the URI appearing as the value of <code>xsl:package/@name</code>)
2383
     *</summary>
2384
     * <returns>return the package name</returns>
2385
     */
2386

    
2387
	public String PackageName {
2388
		get { return package.getName();}
2389
	}
2390

    
2391
	
2392
     /// <summary>Get the version number of the package (the value of the attribute <code>xsl:package/@package-version</code></summary>
2393
     /// @return the package version number
2394

    
2395
	public String Version {
2396
		get { return package.getVersion(); }
2397
	}
2398

    
2399
	
2400
     /// <summary>Link this package with the packages it uses to form an executable stylesheet. This process fixes
2401
     /// up any cross-package references to files, templates, and other components, and checks to ensure
2402
     /// that all such references are consistent.</summary>
2403
     /// <returns> the resulting XsltExecutable</returns>
2404
     
2405
	public XsltExecutable Link()  {
2406
		try {
2407

    
2408
			JCompilation compilation = new JCompilation(processor.Implementation, new JCompilerInfo());
2409
			PreparedStylesheet pss = new PreparedStylesheet(compilation);
2410
			package.getUnderlyingPreparedPackage().updatePreparedStylesheet(pss);
2411
			return new XsltExecutable(processor, pss);
2412
		} catch (net.sf.saxon.trans.XPathException e) {
2413
			throw new StaticError(e);
2414
		}
2415
	}
2416
		
2417

    
2418
	/**
2419
     * <summary>Escape-hatch interface to the underlying implementation class.</summary>
2420
     * <returns>the underlying StylesheetPackage. The interface to StylesheetPackage
2421
     * is not a stable part of the s9api API definition.</returns>
2422
     */
2423

    
2424
	public JStylesheetPackage getUnderlyingPreparedPackage() {
2425
		return package.getUnderlyingPreparedPackage();
2426
	}
2427

    
2428
}
2429

    
2430

    
2431
}
2432

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