Project

Profile

Help

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

he / tags / 9.4.0.7 / hen / csource / api / Saxon.Api / Xslt.cs @ b0b00ab2

1
using System;
2
using System.IO;
3
using System.Xml;
4
using System.Collections;
5
using JStreamSource = javax.xml.transform.stream.StreamSource;
6
using JResult = javax.xml.transform.Result;
7
using JTransformerException = javax.xml.transform.TransformerException;
8
using JOutputURIResolver = net.sf.saxon.lib.OutputURIResolver;
9
using JAugmentedSource = net.sf.saxon.lib.AugmentedSource;
10
using JConfiguration = net.sf.saxon.Configuration;
11
using JLocationProvider = net.sf.saxon.@event.LocationProvider;
12
using JPipelineConfiguration = net.sf.saxon.@event.PipelineConfiguration;
13
using JStructuredQName = net.sf.saxon.om.StructuredQName;
14
using JProperties = java.util.Properties;
15
using JSequenceWriter = net.sf.saxon.@event.SequenceWriter;
16
using JReceiver = net.sf.saxon.@event.Receiver;
17
using JReceiverOptions = net.sf.saxon.@event.ReceiverOptions;
18
using JCompilerInfo = net.sf.saxon.trans.CompilerInfo;
19
using JExpressionPresenter = net.sf.saxon.trace.ExpressionPresenter;
20
using JValidation = net.sf.saxon.lib.Validation;
21
using JDocumentURI = net.sf.saxon.om.DocumentURI;
22
using JDecimalValue = net.sf.saxon.value.DecimalValue;
23
using net.sf.saxon;
24
using JItem = net.sf.saxon.om.Item;
25
using JNodeInfo = net.sf.saxon.om.NodeInfo;
26
using JNodeName = net.sf.saxon.om.NodeName;
27
using JSchemaType = net.sf.saxon.type.SchemaType;
28
using JDocumentInfo = net.sf.saxon.om.DocumentInfo;
29
using JPullProvider = net.sf.saxon.pull.PullProvider;
30
using JPullSource = net.sf.saxon.pull.PullSource;
31
using JProcInstParser = net.sf.saxon.tree.util.ProcInstParser;
32
using net.sf.saxon.dotnet;
33
using CharSequence = java.lang.CharSequence;
34
using JBoolean = java.lang.Boolean;
35

    
36

    
37
namespace Saxon.Api
38
{
39

    
40
    /// <summary>
41
    /// An <c>XsltCompiler</c> object allows XSLT 2.0 stylesheets to be compiled.
42
    /// The compiler holds information that represents the static context
43
    /// for the compilation.
44
    /// </summary>
45
    /// <remarks>
46
    /// <para>To construct an <c>XsltCompiler</c>, use the factory method
47
    /// <c>NewXsltCompiler</c> on the <c>Processor</c> object.</para>
48
    /// <para>An <c>XsltCompiler</c> may be used repeatedly to compile multiple
49
    /// queries. Any changes made to the <c>XsltCompiler</c> (that is, to the
50
    /// static context) do not affect queries that have already been compiled.
51
    /// An <c>XsltCompiler</c> may be used concurrently in multiple threads, but
52
    /// it should not then be modified once initialized.</para>
53
    /// </remarks>
54

    
55
    [Serializable]
56
    public class XsltCompiler
57
    {
58

    
59
        private TransformerFactoryImpl factory;
60
        private Processor processor;
61
        private JConfiguration config;
62
        private JCompilerInfo info;
63
        private Uri baseUri;
64
        private IList errorList = null;
65

    
66
        // internal constructor: the public interface is a factory method
67
        // on the Processor object
68

    
69
        internal XsltCompiler(Processor processor)
70
        {
71
            this.processor = processor;
72
            this.config = processor.config;
73
            this.factory = new TransformerFactoryImpl(config);
74
            this.info = new JCompilerInfo(config.getDefaultXsltCompilerInfo());
75
            info.setURIResolver(config.getURIResolver());
76
            info.setErrorListener(config.getErrorListener());
77
        }
78

    
79
        /// <summary>
80
        /// The base URI of the stylesheet, which forms part of the static context
81
        /// of the stylesheet. This is used for resolving any relative URIs appearing
82
        /// within the stylesheet, for example in <c>xsl:include</c> and <c>xsl:import</c>
83
        /// declarations, in schema locations defined to <c>xsl:import-schema</c>, 
84
        /// or as an argument to the <c>document()</c> or <c>doc()</c> function.
85
        /// </summary>
86
        /// <remarks>
87
        /// This base URI is used only if the input supplied to the <c>Compile</c> method
88
        /// does not provide its own base URI. It is therefore used on the version of the
89
        /// method that supplies input from a <c>Stream</c>. On the version that supplies
90
        /// input from an <c>XmlReader</c>, this base URI is used only if the <c>XmlReader</c>
91
        /// does not have its own base URI.
92
        /// </remarks>
93

    
94

    
95
        public Uri BaseUri
96
        {
97
            get { return baseUri; }
98
            set { baseUri = value; }
99
        }
100

    
101

    
102
        /// <summary>
103
        /// Get the Processor from which this XsltCompiler was constructed
104
        /// </summary>
105
        public Processor Processor
106
        {
107
            get { return processor; }
108
            set { processor = value; }
109
        }
110

    
111
        /// <summary>
112
        /// An <c>XmlResolver</c>, which will be used to resolve URI references while compiling
113
        /// a stylesheet
114
        /// </summary>
115
        /// <remarks>
116
        /// If no <c>XmlResolver</c> is set for the <c>XsltCompiler</c>, the <c>XmlResolver</c>
117
        /// is used that was set on the <c>Processor</c> at the time <c>NewXsltCompiler</c>
118
        /// was called.
119
        /// </remarks>
120

    
121
        public XmlResolver XmlResolver
122
        {
123
            get
124
            {
125
                return ((DotNetURIResolver)info.getURIResolver()).getXmlResolver();
126
            }
127
            set
128
            {
129
                info.setURIResolver(new DotNetURIResolver(value));
130
            }
131
        }
132

    
133
        /// <summary>
134
        /// The <c>SchemaAware</c> property determines whether the stylesheet is schema-aware. By default, a stylesheet
135
        /// is schema-aware if it contains one or more <code>xsl:import-schema</code> declarations. This option allows
136
        /// a stylesheet to be marked as schema-aware even if it does not contain such a declaration.
137
        /// </summary>
138
        /// <remarks>
139
        /// <para>If the stylesheet is not schema-aware, then schema-validated input documents will be rejected.</para>
140
        /// <para>The reason for this option is that it is expensive to generate code that can handle typed input
141
        /// documents when they will never arise in practice.</para>
142
        /// <para>The initial setting of this property is false, regardless of whether or not the <c>Processor</c>
143
        /// is schema-aware. Setting this property to true if the processor is not schema-aware will cause an Exception.</para>
144
        /// </remarks>
145
         
146
        public bool SchemaAware
147
        {
148
            get
149
            {
150
                return info.isSchemaAware();
151
            }
152
            set
153
            {
154
                info.setSchemaAware(value);
155
            }
156
        }
157

    
158
        /// <summary>
159
        /// The <c>XsltLanguageVersion</c> property determines whether the version of the XSLT language specification
160
        /// 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.
161
        /// The value 0.0 (which is the initial default) indicates that the value is to be taken from the <c>version</c>
162
        /// attribute of the <c>xsl:stylesheet</c> element.
163
        /// </summary>
164
        /// <remarks>
165
        /// <para>Values that are not numerically equal to one of the above values are rejected.</para>
166
        /// <para>A warning is output (unless suppressed) when the XSLT language version supported by the processor
167
        /// is different from the value of the <c>version</c> attribute of the <c>xsl:stylesheet</c> element.</para>
168
        /// <para>XSLT 3.0 features are supported only in Saxon-PE and Saxon-EE. Setting the value to 3.0 under 
169
        /// Saxon-HE will cause an error if (and only if) the stylesheet actually uses XSLT 3.0 constructs.</para>
170
        /// </remarks>
171

    
172
        public string XsltLanguageVersion
173
        {
174
            get
175
            {
176
                return info.getXsltVersion().toString();
177
            }
178
            set
179
            {
180
                info.setXsltVersion((JDecimalValue)JDecimalValue.makeDecimalValue(value.ToString(), true));
181
            }
182
        }
183

    
184
        /// <summary>
185
        /// List of errors. The caller should supply an empty list before calling Compile;
186
        /// the processor will then populate the list with error information obtained during
187
        /// the compilation. Each error will be included as an object of type StaticError.
188
        /// If no error list is supplied by the caller, error information will be written to
189
        /// the standard error stream.
190
        /// </summary>
191
        /// <remarks>
192
        /// By supplying a custom List with a user-written add() method, it is possible to
193
        /// intercept error conditions as they occur.
194
        /// </remarks>
195

    
196
        public IList ErrorList
197
        {
198
            set
199
            {
200
                errorList = value;
201
                info.setErrorListener(new ErrorGatherer(value));
202
            }
203
            get
204
            {
205
                return errorList;
206
            }
207
        }
208

    
209
        /// <summary>
210
        /// Compile a stylesheet supplied as a Stream.
211
        /// </summary>
212
        /// <example>
213
        /// <code>
214
        /// Stream source = new FileStream("input.xsl", FileMode.Open, FileAccess.Read);
215
        /// XsltExecutable q = compiler.Compile(source);
216
        /// source.Close();
217
        /// </code>
218
        /// </example>
219
        /// <param name="input">A stream containing the source text of the stylesheet</param>
220
        /// <returns>An <c>XsltExecutable</c> which represents the compiled stylesheet object.
221
        /// The XsltExecutable may be loaded as many times as required, in the same or a different
222
        /// thread. The <c>XsltExecutable</c> is not affected by any changes made to the <c>XsltCompiler</c>
223
        /// once it has been compiled.</returns>
224
        /// <remarks>
225
        /// <para>If the stylesheet contains any <c>xsl:include</c> or <c>xsl:import</c> declarations,
226
        /// then the <c>BaseURI</c> property must be set to allow these to be resolved.</para>
227
        /// <para>The stylesheet is contained in the part of the input stream between its current
228
        /// position and the end of the stream. It is the caller's responsibility to close the input 
229
        /// stream after use. If the compilation succeeded, then on exit the stream will be 
230
        /// exhausted; if compilation failed, the current position of the stream on exit is
231
        /// undefined.</para>
232
        /// </remarks>
233

    
234
        public XsltExecutable Compile(Stream input)
235
        {
236
            try
237
            {
238
                JStreamSource ss = new JStreamSource(new DotNetInputStream(input));
239
                if (baseUri != null)
240
                {
241
                    ss.setSystemId(baseUri.ToString());
242
                }
243
                PreparedStylesheet pss = (PreparedStylesheet)factory.newTemplates(ss, info);
244
                return new XsltExecutable(pss);
245
            }
246
            catch (JTransformerException err)
247
            {
248
                throw new StaticError(err);
249
            }
250
        }
251

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

    
278
        public XsltExecutable Compile(TextReader input)
279
        {
280
            JStreamSource ss = new JStreamSource(new DotNetReader(input));
281
            if (baseUri != null)
282
            {
283
                ss.setSystemId(baseUri.ToString());
284
            }
285
            PreparedStylesheet pss = (PreparedStylesheet)factory.newTemplates(ss, info);
286
            return new XsltExecutable(pss);
287
        }
288

    
289
        /// <summary>
290
        /// Compile a stylesheet, retrieving the source using a URI.
291
        /// </summary>
292
        /// <remarks>
293
        /// The document located via the URI is parsed using the <c>System.Xml</c> parser. This
294
        /// URI is used as the base URI of the stylesheet: the <c>BaseUri</c> property of the
295
        /// <c>Compiler</c> is ignored.
296
        /// </remarks>
297
        /// <param name="uri">The URI identifying the location where the stylesheet document can be
298
        /// found</param>
299
        /// <returns>An <c>XsltExecutable</c> which represents the compiled stylesheet object.
300
        /// The XsltExecutable may be run as many times as required, in the same or a different
301
        /// thread. The <c>XsltExecutable</c> is not affected by any changes made to the <c>XsltCompiler</c>
302
        /// once it has been compiled.</returns>
303

    
304
        public XsltExecutable Compile(Uri uri)
305
        {
306
            Object obj = XmlResolver.GetEntity(uri, "application/xml", Type.GetType("System.IO.Stream"));
307
            if (obj is Stream)
308
            {
309
                try
310
                {
311
                    XmlReaderSettings settings = new XmlReaderSettings();
312
                    settings.ProhibitDtd = false;   // must expand entity references
313
                    settings.XmlResolver = XmlResolver;
314
                    settings.IgnoreWhitespace = false;
315
                    settings.ValidationType = ValidationType.None;
316
                    XmlReader parser = XmlReader.Create((Stream)obj, settings, uri.ToString());
317
                    //XmlReader parser = new XmlTextReader(uri.ToString(), (Stream)obj);
318
                    //((XmlTextReader)parser).Normalization = true;
319
                    //((XmlTextReader)parser).WhitespaceHandling = WhitespaceHandling.All;
320
                    //((XmlTextReader)parser).XmlResolver = XmlResolver;
321
                    // Always need a validating parser, because that's the only way to get entity references expanded
322
                    //parser = new XmlValidatingReader(parser);
323
                    //((XmlValidatingReader)parser).ValidationType = ValidationType.None;
324
                    JPullSource source = new JPullSource(new DotNetPullProvider(parser));
325
                    PreparedStylesheet pss = (PreparedStylesheet)factory.newTemplates(source, info);
326
                    return new XsltExecutable(pss);
327
                }
328
                finally
329
                {
330
                    ((Stream)obj).Close();
331
                }
332
            }
333
            else
334
            {
335
                throw new ArgumentException("Invalid type of result from XmlResolver.GetEntity: " + obj);
336
            }
337
        }
338

    
339
        /// <summary>
340
        /// Compile a stylesheet, delivered using an XmlReader.
341
        /// </summary>
342
        /// <remarks>
343
        /// The <c>XmlReader</c> is responsible for parsing the document; this method builds a tree
344
        /// representation of the document (in an internal Saxon format) and compiles it.
345
        /// The <c>XmlReader</c> will be used as supplied; it is the caller's responsibility to
346
        /// ensure that the settings of the <c>XmlReader</c> are consistent with the requirements
347
        /// of the XSLT specification (for example, that entity references are expanded and whitespace
348
        /// is preserved).
349
        /// </remarks>
350
        /// <remarks>
351
        /// If the <c>XmlReader</c> has a <c>BaseUri</c> property, then that property determines
352
        /// the base URI of the stylesheet module, which is used when resolving any <c>xsl:include</c>
353
        /// or <c>xsl:import</c> declarations. If the <c>XmlReader</c> has no <c>BaseUri</c>
354
        /// property, then the <c>BaseUri</c> property of the <c>Compiler</c> is used instead.
355
        /// An <c>ArgumentNullException</c> is thrown if this property has not been supplied.
356
        /// </remarks>
357
        /// <param name="reader">The XmlReader (that is, the XML parser) used to supply the document containing
358
        /// the principal stylesheet module.</param>
359
        /// <returns>An <c>XsltExecutable</c> which represents the compiled stylesheet object.
360
        /// The XsltExecutable may be run as many times as required, in the same or a different
361
        /// thread. The <c>XsltExecutable</c> is not affected by any changes made to the <c>XsltCompiler</c>
362
        /// once it has been compiled.</returns>
363

    
364

    
365
        public XsltExecutable Compile(XmlReader reader)
366
        {
367
            DotNetPullProvider pp = new DotNetPullProvider(reader);
368
            JPipelineConfiguration pipe = config.makePipelineConfiguration();
369
            pipe.setLocationProvider(pp);
370
            pp.setPipelineConfiguration(pipe);
371
            // pp = new PullTracer(pp);  /* diagnostics */
372
            JPullSource source = new JPullSource(pp);
373
            String baseu = reader.BaseURI;
374
            if (baseu == null || baseu == String.Empty)
375
            {
376
                // if no baseURI is supplied by the XmlReader, use the one supplied to this Compiler
377
                if (baseUri == null)
378
                {
379
                    throw new ArgumentNullException("BaseUri");
380
                }
381
                baseu = baseUri.ToString();
382
                pp.setBaseURI(baseu);
383
            }
384
            source.setSystemId(baseu);
385
            PreparedStylesheet pss = (PreparedStylesheet)factory.newTemplates(source, info);
386
            return new XsltExecutable(pss);
387
        }
388

    
389
        /// <summary>
390
        /// Compile a stylesheet, located at an XdmNode. This may be a document node whose
391
        /// child is an <c>xsl:stylesheet</c> or <c>xsl:transform</c> element, or it may be
392
        /// the <c>xsl:stylesheet</c> or <c>xsl:transform</c> element itself.
393
        /// </summary>
394
        /// <param name="node">The document node or the outermost element node of the document
395
        /// containing the principal stylesheet module.</param>
396
        /// <returns>An <c>XsltExecutable</c> which represents the compiled stylesheet object.
397
        /// The XsltExecutable may be run as many times as required, in the same or a different
398
        /// thread. The <c>XsltExecutable</c> is not affected by any changes made to the <c>XsltCompiler</c>
399
        /// once it has been compiled.</returns>
400

    
401
        public XsltExecutable Compile(XdmNode node)
402
        {
403
            PreparedStylesheet pss = (PreparedStylesheet)factory.newTemplates((JNodeInfo)node.value, info);
404
            return new XsltExecutable(pss);
405
        }
406

    
407
        /// <summary>Locate and compile a stylesheet identified by an &lt;?xml-stylesheet?&gt;
408
        /// processing instruction within a source document.
409
        /// </summary>
410
        /// <param name="source">The document node of the source document containing the
411
        /// xml-stylesheet processing instruction.</param>
412
        /// <returns>An <c>XsltExecutable</c> which represents the compiled stylesheet object.</returns>
413
        /// <remarks>There are some limitations in the current implementation. The media type
414
        /// is ignored, as are the other parameters of the xml-stylesheet instruction. The
415
        /// href attribute must either reference an embedded stylesheet within the same
416
        /// document or a non-embedded external stylesheet.</remarks>
417

    
418
        public XsltExecutable CompileAssociatedStylesheet(XdmNode source)
419
        {
420
            // TODO: lift the restrictions
421
            if (source == null || source.NodeKind != XmlNodeType.Document)
422
            {
423
                throw new ArgumentException("Source must be a document node");
424
            }
425
            IEnumerator kids = source.EnumerateAxis(XdmAxis.Child);
426
            QName xmlstyle = new QName("", "xml-stylesheet");
427
            while (kids.MoveNext())
428
            {
429
                XdmNode n = (XdmNode)kids.Current;
430
                if (n.NodeKind == XmlNodeType.ProcessingInstruction &&
431
                    n.NodeName.Equals(xmlstyle))
432
                {
433
                    // TODO: check the media type
434
                    String href = JProcInstParser.getPseudoAttribute(n.StringValue, "href");
435
                    if (href == null)
436
                    {
437
                        throw new DynamicError("xml-stylesheet processing instruction has no href attribute");
438
                    }
439
                    String fragment = null;
440
                    int hash = href.LastIndexOf('#');
441
                    if (hash == 0)
442
                    {
443
                        if (href.Length == 1)
444
                        {
445
                            throw new DynamicError("Relative URI of '#' is invalid");
446
                        }
447
                        fragment = href.Substring(1);
448
                        JNodeInfo target = ((JDocumentInfo)source.value).selectID(fragment, true);
449
                        XdmNode targetWrapper = null;
450
                        if (target == null)
451
                        {
452
                            // There's a problem here because the Microsoft XML parser doesn't
453
                            // report id values, so selectID() will never work. We work around that
454
                            // by looking for an attribute named "id" appearing on an xsl:stylesheet
455
                            // or xsl:transform element
456
                            QName qid = new QName("", "id");
457
                            IEnumerator en = source.EnumerateAxis(XdmAxis.Descendant);
458
                            while (en.MoveNext())
459
                            {
460
                                XdmNode x = (XdmNode)en.Current;
461
                                if (x.NodeKind == XmlNodeType.Element &&
462
                                        x.NodeName.Uri == "http://www.w3.org/1999/XSL/Transform" &&
463
                                        (x.NodeName.LocalName == "stylesheet" || x.NodeName.LocalName == "transform" &&
464
                                        x.GetAttributeValue(qid) == fragment))
465
                                {
466
                                    targetWrapper = x;
467
                                }
468
                            }
469
                        }
470
                        else
471
                        {
472
                            targetWrapper = (XdmNode)XdmValue.Wrap(target);
473
                        }
474
                        if (targetWrapper == null)
475
                        {
476
                            throw new DynamicError("No element with id='" + fragment + "' found");
477
                        }
478
                        return Compile(targetWrapper);
479
                    }
480
                    else if (hash > 0)
481
                    {
482
                        throw new NotImplementedException("href cannot identify an embedded stylesheet in a different document");
483
                    }
484
                    else
485
                    {
486
                        Uri uri = new Uri(n.BaseUri, href);
487
                        return Compile(uri);
488
                    }
489
                }
490
            }
491
            throw new DynamicError("xml-stylesheet processing instruction not found");
492
        }
493
    }
494

    
495
    /// <summary>
496
    /// An <c>XsltExecutable</c> represents the compiled form of a stylesheet. To execute the stylesheet,
497
    /// it must first be loaded to form an <c>XsltTransformer</c>.
498
    /// </summary>
499
    /// <remarks>
500
    /// <para>An <c>XsltExecutable</c> is immutable, and therefore thread-safe. It is simplest to
501
    /// load a new <c>XsltEvaluator</c> each time the stylesheet is to be run. However, the 
502
    /// <c>XsltEvaluator</c> is serially reusable within a single thread.</para>
503
    /// <para>An <c>XsltExecutable</c> is created by using one of the <c>Compile</c>
504
    /// methods on the <c>XsltCompiler</c> class.</para>
505
    /// </remarks>    
506

    
507
    [Serializable]
508
    public class XsltExecutable
509
    {
510

    
511
        private PreparedStylesheet pss;
512

    
513
        // internal constructor
514

    
515
        internal XsltExecutable(PreparedStylesheet pss)
516
        {
517
            this.pss = pss;
518
        }
519

    
520
        /// <summary>
521
        /// Load the stylesheet to prepare it for execution.
522
        /// </summary>
523
        /// <returns>
524
        /// An <c>XsltTransformer</c>. The returned <c>XsltTransformer</c> can be used to
525
        /// set up the dynamic context for stylesheet evaluation, and to run the stylesheet.
526
        /// </returns>
527

    
528
        public XsltTransformer Load()
529
        {
530
            Controller c = (Controller)pss.newTransformer();
531
            return new XsltTransformer(c);
532
        }
533

    
534
        /// <summary>
535
        /// Output an XML representation of the compiled code of the stylesheet, for purposes of 
536
        /// diagnostics and instrumentation
537
        /// </summary>
538
        /// <param name="destination">The destination for the diagnostic output</param>
539
        
540
        public void Explain(XmlDestination destination) {
541
            JConfiguration config = pss.getConfiguration();
542
            JResult result = destination.GetResult(config.makePipelineConfiguration());          
543
            JProperties properties = new JProperties();
544
            properties.setProperty("indent", "yes");
545
            properties.setProperty("{http://saxon.sf.net/}indent-spaces", "2");
546
            JReceiver receiver = config.getSerializerFactory().getReceiver(
547
                result, config.makePipelineConfiguration(), properties);
548
            JExpressionPresenter presenter = new JExpressionPresenter(config, receiver);
549
            pss.explain(presenter);
550
        }
551

    
552
        /// <summary>
553
        /// Escape hatch to the underlying Java implementation object
554
        /// </summary>
555

    
556
        public PreparedStylesheet Implementation
557
        {
558
            get
559
            {
560
                return pss;
561
            }
562
        }
563

    
564

    
565
    }
566

    
567
    /// <summary inherits="IEnumerable">
568
    /// An <c>XsltTransformer</c> represents a compiled and loaded stylesheet ready for execution.
569
    /// The <c>XsltTransformer</c> holds details of the dynamic evaluation context for the stylesheet.
570
    /// </summary>
571
    /// <remarks>
572
    /// <para>An <c>XsltTransformer</c> should not be used concurrently in multiple threads. It is safe,
573
    /// however, to reuse the object within a single thread to run the same stylesheet several times.
574
    /// Running the stylesheet does not change the context that has been established.</para>
575
    /// <para>An <c>XsltTransformer</c> is always constructed by running the <c>Load</c> method of
576
    /// an <c>XsltExecutable</c>.</para>
577
    /// </remarks>     
578

    
579
    [Serializable]
580
    public class XsltTransformer
581
    {
582

    
583
        private Controller controller;
584
        private JNodeInfo initialContextNode;
585
        private IResultDocumentHandler resultDocumentHandler;
586
        private IMessageListener messageListener;
587
        private JStreamSource streamSource;
588
        private Stream traceFunctionDestination;
589
        
590

    
591
        // internal constructor
592

    
593
        internal XsltTransformer(Controller controller)
594
        {
595
            this.controller = controller;
596
        }
597

    
598
        /// <summary>
599
        /// The initial context item for the stylesheet.
600
        /// </summary>
601
        /// <remarks><para>This may be either a node or an atomic
602
        /// value. Most commonly it will be a document node, which might be constructed
603
        /// using the <c>Build</c> method of the <c>DocumentBuilder</c> object.</para>
604
        /// <para>Note that this can be inefficient if the stylesheet uses <c>xsl:strip-space</c>
605
        /// to strip whitespace, or <c>input-type-annotations="strip"</c> to remove type
606
        /// annotations, since this will result in the transformation operating on a virtual document
607
        /// implemented as a view or wrapper of the supplied document.</para>
608
        /// </remarks>
609

    
610
        public XdmNode InitialContextNode
611
        {
612
            get { return (initialContextNode == null ? null : (XdmNode)XdmValue.Wrap(initialContextNode)); }
613
            set { initialContextNode = (value == null ? null : (JNodeInfo)value.Unwrap()); }
614
        }
615

    
616
        /// <summary>
617
        /// Supply the principal input document for the transformation in the form of a stream.
618
        /// </summary>
619
        /// <remarks>
620
        /// <para>If this method is used, the <c>InitialContextNode</c> is ignored.</para>
621
        /// <para>The supplied stream will be consumed by the <c>Run()</c> method.
622
        /// Closing the input stream after use is the client's responsibility.</para>
623
        /// <para>A base URI must be supplied in all cases. It is used to resolve relative
624
        /// URI references appearing within the input document.</para>
625
        /// <para>Schema validation is applied to the input document according to the value of
626
        /// the <c>SchemaValidationMode</c> property.</para>
627
        /// <para>Whitespace stripping is applied according to the value of the
628
        /// <c>xsl:strip-space</c> and <c>xsl:preserve-space</c> declarations in the stylesheet.</para>
629
        /// </remarks>
630
        /// <param name="input">
631
        /// The stream containing the source code of the principal input document to the transformation. The document
632
        /// node at the root of this document will be the initial context node for the transformation.
633
        /// </param>
634
        /// <param name="baseUri">
635
        /// The base URI of the principal input document. This is used for example by the <c>document()</c>
636
        /// function if the document contains links to other documents in the form of relative URIs.</param>
637

    
638
        public void SetInputStream(Stream input, Uri baseUri) 
639
        {
640
            streamSource = new JStreamSource(new DotNetInputStream(input), baseUri.ToString());
641
        }
642

    
643
        /// <summary>
644
        /// The initial mode for the stylesheet. This is either a QName, for a 
645
        /// named mode, or null, for the unnamed (default) mode.
646
        /// </summary>
647

    
648
        public QName InitialMode
649
        {
650
            get
651
            {
652
                JStructuredQName mode = controller.getInitialMode().getModeName();
653
                if (mode == null)
654
                {
655
                    return null;
656
                }
657
                return QName.FromClarkName(mode.getClarkName());
658
            }
659
            set
660
            {
661
                controller.setInitialMode(value.ClarkName);
662
            }
663
        }
664

    
665
        /// <summary>
666
        /// The initial template for the stylesheet. This is either a QName, for a 
667
        /// named template, or null, if no initial template has been set.
668
        /// </summary>
669
        /// <exception cref="DynamicError">Setting this property to the name of a template
670
        /// that does not exist in the stylesheet throws a DynamicError with error 
671
        /// code XTDE0040. Setting it to the name of a template that has template
672
        /// parameters throws a DynamicError with error code XTDE0060.</exception>
673

    
674
        public QName InitialTemplate
675
        {
676
            get
677
            {
678
                String name = controller.getInitialTemplate();
679
                if (name == null)
680
                {
681
                    return null;
682
                }
683
                return QName.FromClarkName(name);
684
            }
685
            set
686
            {
687
                try
688
                {
689
                    controller.setInitialTemplate(value.ClarkName);
690
                }
691
                catch (javax.xml.transform.TransformerException err)
692
                {
693
                    throw new DynamicError(err);
694
                }
695
            }
696
        }
697

    
698
        /// <summary>
699
        /// The base output URI, which acts as the base URI for resolving the <c>href</c>
700
        /// attribute of <c>xsl:result-document</c>.
701
        /// </summary>
702

    
703
        public Uri BaseOutputUri
704
        {
705
            get
706
            {
707
                return new Uri(controller.getBaseOutputURI());
708
            }
709
            set
710
            {
711
                controller.setBaseOutputURI(value.ToString());
712
            }
713
        }
714

    
715
        public RecoveryPolicy RecoveryPolicy
716
        {
717
            get
718
            {
719
                switch (controller.getRecoveryPolicy())
720
                {
721
                    case Configuration.RECOVER_SILENTLY:
722
                        return RecoveryPolicy.RecoverSilently;
723
                    case Configuration.RECOVER_WITH_WARNINGS:
724
                        return RecoveryPolicy.RecoverWithWarnings;
725
                    default: return RecoveryPolicy.DoNotRecover;
726
                }
727
            }
728
            set
729
            {
730
                controller.setRecoveryPolicy(
731
                    value == RecoveryPolicy.RecoverSilently ? Configuration.RECOVER_SILENTLY :
732
                    value == RecoveryPolicy.RecoverWithWarnings ? Configuration.RECOVER_WITH_WARNINGS :
733
                    Configuration.DO_NOT_RECOVER);
734
            }
735
        }
736

    
737
        /// <summary>
738
        /// The <c>SchemaValidationMode</c> to be used in this transformation, especially for documents
739
        /// loaded using the <c>doc()</c>, <c>document()</c>, or <c>collection()</c> functions.
740
        /// </summary>
741
        /// 
742

    
743
        public SchemaValidationMode SchemaValidationMode
744
        {
745
            get
746
            {
747
                switch (controller.getSchemaValidationMode())
748
                {
749
                    case JValidation.STRICT:
750
                        return SchemaValidationMode.Strict;
751
                    case JValidation.LAX:
752
                        return SchemaValidationMode.Lax;
753
                    case JValidation.STRIP:
754
                        return SchemaValidationMode.None;
755
                    case JValidation.PRESERVE:
756
                        return SchemaValidationMode.Preserve;
757
                    case JValidation.DEFAULT:
758
                    default:
759
                        return SchemaValidationMode.Unspecified;
760
                }
761
            }
762

    
763
            set
764
            {
765
                switch (value)
766
                {
767
                    case SchemaValidationMode.Strict:
768
                        controller.setSchemaValidationMode(JValidation.STRICT);
769
                        break;
770
                    case SchemaValidationMode.Lax:
771
                        controller.setSchemaValidationMode(JValidation.LAX);
772
                        break;
773
                    case SchemaValidationMode.None:
774
                        controller.setSchemaValidationMode(JValidation.STRIP);
775
                        break;
776
                    case SchemaValidationMode.Preserve:
777
                        controller.setSchemaValidationMode(JValidation.PRESERVE);
778
                        break;
779
                    case SchemaValidationMode.Unspecified:
780
                    default:
781
                        controller.setSchemaValidationMode(JValidation.DEFAULT);
782
                        break;
783
                }
784
            }
785
        }
786

    
787

    
788

    
789
        /// <summary>
790
        /// The <c>XmlResolver</c> to be used at run-time to resolve and dereference URIs
791
        /// supplied to the <c>doc()</c> and <c>document()</c> functions.
792
        /// </summary>
793

    
794
        public XmlResolver InputXmlResolver
795
        {
796
            get
797
            {
798
                return ((DotNetURIResolver)controller.getURIResolver()).getXmlResolver();
799
            }
800
            set
801
            {
802
                controller.setURIResolver(new DotNetURIResolver(value));
803
            }
804
        }
805

    
806
        /// <summary>
807
        /// The <c>IResultDocumentHandler</c> to be used at run-time to process the output
808
        /// produced by any <c>xsl:result-document</c> instruction with an <c>href</c>
809
        /// attribute.
810
        /// </summary>
811
        /// <remarks>
812
        /// In the absence of a user-supplied result document handler, the <c>href</c>
813
        /// attribute of the <c>xsl:result-document</c> instruction must be a valid relative
814
        /// URI, which is resolved against the value of the <c>BaseOutputUri</c> property,
815
        /// and the resulting absolute URI must identify a writable resource (typically
816
        /// a file in filestore, using the <c>file:</c> URI scheme).
817
        /// </remarks>
818

    
819
        public IResultDocumentHandler ResultDocumentHandler
820
        {
821
            get
822
            {
823
                return resultDocumentHandler;
824
            }
825
            set
826
            {
827
                resultDocumentHandler = value;
828
                controller.setOutputURIResolver(new ResultDocumentHandlerWrapper(value, controller.makePipelineConfiguration()));
829
            }
830
        }
831

    
832
        /// <summary>
833
        /// Listener for messages output using &lt;xsl:message&gt;. 
834
        /// <para>The caller may supply a message listener before calling <c>Run</c>;
835
        /// the processor will then invoke the listener once for each message generated during
836
        /// the transformation. Each message will be output as an object of type <c>XdmNode</c>
837
        /// representing a document node.</para>
838
        /// <para>If no message listener is supplied by the caller, message information will be written to
839
        /// the standard error stream.</para>
840
        /// </summary>
841
        /// <remarks>
842
        /// <para>Each message is presented as an XML document node. Calling <c>ToString()</c>
843
        /// on the message object will usually generate an acceptable representation of the
844
        /// message.</para>
845
        /// <para>When the &lt;xsl:message&gt; instruction specifies <c>terminate="yes"</c>,
846
        /// the message is first notified using this interface, and then an exception is thrown
847
        /// which terminates the transformation.</para>
848
        /// </remarks>
849

    
850
        public IMessageListener MessageListener
851
        {
852
            set
853
            {
854
                messageListener = value;
855
                JPipelineConfiguration pipe = controller.makePipelineConfiguration();
856
                controller.setMessageEmitter(new MessageListenerProxy(pipe, value));
857
            }
858
            get
859
            {
860
                return messageListener;
861
            }
862
        }
863

    
864
        /// <summary>
865
        /// Destination for output of messages using &lt;trace()&gt;. 
866
        /// <para>If no message listener is supplied by the caller, message information will be written to
867
        /// the standard error stream.</para>
868
        /// </summary>
869
        /// <remarks>
870
        /// <para>The supplied destination is ignored if a <c>TraceListener</c> is in use.</para>
871
        /// </remarks>
872

    
873
        public Stream TraceFunctionDestination
874
        {
875
            set
876
            {
877
                traceFunctionDestination = value;
878
                controller.setTraceFunctionDestination(
879
                    new java.io.PrintStream(new DotNetOutputStream(value)));
880
            }
881
            get
882
            {
883
                return traceFunctionDestination;
884
            }
885
        }
886

    
887

    
888

    
889
        /// <summary>
890
        /// Set the value of a stylesheet parameter.
891
        /// </summary>
892
        /// <param name="name">The name of the parameter, expressed
893
        /// as a QName. If a parameter of this name has been declared in the
894
        /// stylesheet, the given value will be assigned to the variable. If the
895
        /// variable has not been declared, calling this method has no effect (it is
896
        /// not an error).</param>
897
        /// <param name="value">The value to be given to the parameter.
898
        /// If the parameter declaration defines a required type for the variable, then
899
        /// this value will be converted in the same way as arguments to function calls
900
        /// (for example, numeric promotion is applied).</param>
901

    
902
        public void SetParameter(QName name, XdmValue value)
903
        {
904
            controller.setParameter(name.ClarkName, value.Unwrap());
905
        }
906

    
907
        /// <summary>
908
        /// Run the transformation, sending the result to a specified destination.
909
        /// </summary>
910
        /// <param name="destination">
911
        /// The destination for the results of the stylesheet. The class <c>XmlDestination</c>
912
        /// is an abstraction that allows a number of different kinds of destination
913
        /// to be specified.
914
        /// </param>
915
        /// <exception cref="DynamicError">Throws a DynamicError if the transformation
916
        /// fails.</exception>
917

    
918
        public void Run(XmlDestination destination)
919
        {
920
            try
921
            {
922
                controller.setOutputProperties(destination.GetOutputProperties());
923
                if (streamSource != null)
924
                {
925
                    controller.transform(streamSource, destination.GetResult(controller.makePipelineConfiguration()));
926
                }
927
                else if (initialContextNode != null)
928
                {
929
                    JDocumentInfo doc = initialContextNode.getDocumentRoot();
930
		    if(doc != null) {
931
                    	controller.registerDocument(doc, (doc.getBaseURI()==null ? null : new JDocumentURI(doc.getBaseURI())));
932
		    }
933
                    controller.transform(initialContextNode, destination.GetResult(controller.makePipelineConfiguration()));
934
                }
935
                else
936
                {
937
                    controller.transform(null, destination.GetResult(controller.makePipelineConfiguration()));
938
                }
939
                destination.Close();
940
            }
941
            catch (javax.xml.transform.TransformerException err)
942
            {
943
                throw new DynamicError(err);
944
            }
945
        }
946

    
947
        /// <summary>
948
        /// Escape hatch to the underlying Java implementation
949
        /// </summary>
950

    
951
        public Controller Implementation
952
        {
953
            get { return controller; }
954
        }
955

    
956

    
957
    }
958

    
959
    /// <summary>
960
    /// RecoveryPolicy is an enumeration of the different actions that can be taken when a "recoverable error" occurs
961
    /// </summary>
962

    
963
    public enum RecoveryPolicy
964
    {
965
        /// <summary>
966
        /// Ignore the error, take the recovery action, do not produce any message
967
        /// </summary>
968
        RecoverSilently,
969

    
970
        /// <summary>
971
        /// Take the recovery action after outputting a warning message
972
        /// </summary>
973
        RecoverWithWarnings,
974

    
975
        /// <summary>
976
        /// Treat the error as fatal
977
        /// </summary>
978
        DoNotRecover
979

    
980
    }
981

    
982

    
983

    
984
    ///<summary>An <c>IResultDocumentHandler</c> can be nominated to handle output
985
    /// produced by the <c>xsl:result-document</c> instruction in an XSLT stylesheet.
986
    ///</summary>
987
    ///<remarks>
988
    ///<para>This interface affects any <c>xsl:result-document</c> instruction
989
    /// executed by the stylesheet, provided that it has an <c>href</c> attribute.</para> 
990
    ///<para>If no <c>IResultDocumentHandler</c> is nominated (in the
991
    /// <c>IResultDocumentHandler</c> property of the <c>XsltTransformer</c>), the output
992
    /// of <code>xsl:result-document</code> is serialized, and is written to the file
993
    /// or other resource identified by the URI in the <c>href</c> attribute, resolved
994
    /// (if it is relative) against the URI supplied in the <c>BaseOutputUri</c> property
995
    /// of the <c>XsltTransformer</c>.</para>
996
    ///<para>If an <c>IResultDocumentHandler</c> is nominated, however, its
997
    /// <c>HandleResultDocument</c> method will be called whenever an <c>xsl:result-document</c>
998
    /// instruction with an <c>href</c> attribute is evaluated, and the generated result tree
999
    /// will be passed to the <c>XmlDestination</c> returned by that method.</para> 
1000
    ///</remarks>
1001

    
1002
    public interface IResultDocumentHandler
1003
    {
1004

    
1005
        /// <summary> Handle output produced by the <c>xsl:result-document</c>
1006
        /// instruction in an XSLT stylesheet. This method is called by the XSLT processor
1007
        /// when an <c>xsl:result-document</c> with an <c>href</c> attribute is evaluated.
1008
        /// </summary>
1009
        /// <param name="href">An absolute or relative URI. This will be the effective value of the 
1010
        /// <c>href</c> attribute of the <c>xsl:result-document</c> in the stylesheet.</param>
1011
        /// <param name="baseUri">The base URI that should be used for resolving the value of
1012
        /// <c>href</c> if it is relative. This will always be the value of the <c>BaseOutputUri</c>
1013
        /// property of the <c>XsltTransformer</c>.</param>
1014
        /// <returns>An <c>XmlDestination</c> to handle the result tree produced by the
1015
        /// <c>xsl:result-document</c> instruction. The <c>Close</c> method of the returned
1016
        /// <c>XmlDestination</c> will be called when the output is complete.</returns>
1017
        /// <remarks>
1018
        /// <para>The XSLT processor will ensure that the stylesheet cannot create
1019
        /// two distinct result documents which are sent to the same URI. It is the responsibility
1020
        /// of the <c>IResultDocumentHandler</c> to ensure that two distinct result documents are
1021
        /// not sent to the same <c>XmlDestination</c>. Failure to observe this rule can result
1022
        /// in output streams being incorrectly closed.
1023
        /// </para>
1024
        /// <para>Note that more than one result document can be open at the same time,
1025
        /// and that the order of opening, writing, and closing result documents chosen
1026
        /// by the processor does not necessarily bear any direct resemblance to the way
1027
        /// that the XSLT source code is written.</para></remarks>
1028

    
1029
        XmlDestination HandleResultDocument(string href, Uri baseUri);
1030

    
1031
    }
1032

    
1033
    internal class ResultDocumentHandlerWrapper : JOutputURIResolver
1034
    {
1035

    
1036
        private IResultDocumentHandler handler;
1037
        private ArrayList resultList = new ArrayList();
1038
        private ArrayList destinationList = new ArrayList();
1039
        private JPipelineConfiguration pipe;
1040

    
1041
        public ResultDocumentHandlerWrapper(IResultDocumentHandler handler, JPipelineConfiguration pipe)
1042
        {
1043
            this.handler = handler;
1044
            this.pipe = pipe;
1045
        }
1046

    
1047
        public JResult resolve(String href, String baseString)
1048
        {
1049
            Uri baseUri;
1050
            try
1051
            {
1052
                baseUri = new Uri(baseString);
1053
            }
1054
            catch (System.UriFormatException err)
1055
            {
1056
                throw new JTransformerException("Invalid base output URI " + baseString, err);
1057
            }
1058
            XmlDestination destination = handler.HandleResultDocument(href, baseUri);
1059
            JResult result = destination.GetResult(pipe);
1060
            resultList.Add(result);
1061
            destinationList.Add(destination);
1062
            return result;
1063
        }
1064

    
1065
        public void close(JResult result)
1066
        {
1067
            for (int i = 0; i < resultList.Count; i++)
1068
            {
1069
                if (Object.ReferenceEquals(resultList[i], result))
1070
                {
1071
                    ((XmlDestination)destinationList[i]).Close();
1072
                    resultList.RemoveAt(i);
1073
                    destinationList.RemoveAt(i);
1074
                    return;
1075
                }
1076
            }
1077
        }
1078
    }
1079

    
1080
    ///<summary>An <c>IMessageListener</c> can be nominated to handle output
1081
    /// produced by the <c>xsl:message</c> instruction in an XSLT stylesheet.
1082
    ///</summary>
1083
    ///<remarks>
1084
    ///<para>This interface affects any <c>xsl:message</c> instruction
1085
    /// executed by the stylesheet.</para> 
1086
    ///<para>If no <c>IMessageListener</c> is nominated (in the
1087
    /// <c>MessageListener</c> property of the <c>XsltTransformer</c>), the output
1088
    /// of <code>xsl:message</code> is serialized, and is written to standard error
1089
    /// output stream.</para>
1090
    ///<para>If an <c>IMessageListener</c> is nominated, however, its
1091
    /// <c>Message</c> method will be called whenever an <c>xsl:message</c>
1092
    /// instruction is evaluated.</para> 
1093
    ///</remarks>
1094

    
1095

    
1096
    public interface IMessageListener
1097
    {
1098

    
1099
        ///<summary>Handle the output of an <c>xsl:message</c> instruction
1100
        ///in the stylesheet
1101
        ///</summary>
1102
        ///
1103

    
1104
        void Message(XdmNode content, bool terminate, IXmlLocation location);
1105

    
1106
    }
1107

    
1108
    /// <summary>
1109
    /// An <c>IXmlLocation</c> represents the location of a node within an XML document.
1110
    /// It is in two parts: the base URI (or system ID) of the external entity (which will usually
1111
    /// be the XML document entity itself), and the line number of a node relative
1112
    /// to the base URI of the containing external entity.
1113
    /// </summary>
1114
    /// 
1115

    
1116
    public interface IXmlLocation
1117
    {
1118

    
1119
        /// <summary>
1120
        /// The base URI (system ID) of an external entity within an XML document.
1121
        /// Set to null if the base URI is not known (for example, for an XML document
1122
        /// created programmatically where no base URI has been set up).
1123
        /// </summary>
1124

    
1125
        Uri BaseUri { get; set; }
1126

    
1127
        /// <summary>
1128
        /// The line number of a node relative to the start of the external entity.
1129
        /// The value -1 indicates that the line number is not known or not applicable.
1130
        /// </summary>
1131

    
1132
        int LineNumber { get; set; }
1133
    }
1134

    
1135
    internal class XmlLocation : IXmlLocation
1136
    {
1137
        private Uri baseUri;
1138
        private int lineNumber;
1139
        public Uri BaseUri
1140
        {
1141
            get { return baseUri; }
1142
            set { baseUri = value; }
1143
        }
1144
        public int LineNumber
1145
        {
1146
            get { return lineNumber; }
1147
            set { lineNumber = value; }
1148
        }
1149
    }
1150

    
1151

    
1152
    [Serializable]
1153
    internal class MessageListenerProxy : JSequenceWriter
1154
    {
1155

    
1156
        public IMessageListener listener;
1157
        public bool terminate;
1158
        public int locationId;
1159

    
1160
        public MessageListenerProxy(JPipelineConfiguration pipe, IMessageListener ml) : base(pipe)
1161
        {
1162
            listener = ml;
1163
        }
1164

    
1165
        public override void startDocument(int properties)
1166
        {
1167
            terminate = (properties & JReceiverOptions.TERMINATE) != 0;
1168
            locationId = -1;
1169
            base.startDocument(properties);
1170
        }
1171

    
1172
        public override void startElement(JNodeName nameCode, JSchemaType typeCode, int locationId, int properties)
1173
        {
1174
            if (this.locationId == -1)
1175
            {
1176
                this.locationId = locationId;
1177
            }
1178
            base.startElement(nameCode, typeCode, locationId, properties);
1179
        }
1180

    
1181
        public override void characters(CharSequence s, int locationId, int properties)
1182
        {
1183
            if (this.locationId == -1)
1184
            {
1185
                this.locationId = locationId;
1186
            }
1187
            base.characters(s, locationId, properties);
1188
        }
1189

    
1190
        public override void append(JItem item, int locationId, int copyNamespaces)
1191
        {
1192
            if (this.locationId == -1)
1193
            {
1194
                this.locationId = locationId;
1195
            }
1196
            base.append(item, locationId, copyNamespaces);
1197
        }
1198

    
1199
        public override void write(JItem item)
1200
        {
1201
            XmlLocation loc = new XmlLocation();
1202
            if (locationId != -1)
1203
            {
1204
                JLocationProvider provider = getPipelineConfiguration().getLocationProvider();
1205
                loc.BaseUri = new Uri(provider.getSystemId(locationId));
1206
                loc.LineNumber = provider.getLineNumber(locationId);
1207
            }
1208
            listener.Message((XdmNode)XdmItem.Wrap(item), terminate, loc);
1209
        }
1210
    }
1211

    
1212

    
1213
}
1214

    
1215
//
1216
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
1217
// you may not use this file except in compliance with the License. You may obtain a copy of the
1218
// License at http://www.mozilla.org/MPL/
1219
//
1220
// Software distributed under the License is distributed on an "AS IS" basis,
1221
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
1222
// See the License for the specific language governing rights and limitations under the License.
1223
//
1224
// The Original Code is: all this file.
1225
//
1226
// The Initial Developer of the Original Code is Michael H. Kay.
1227
//
1228
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
1229
//
1230
// Contributor(s): none.
1231
//
(12-12/12)