Project

Profile

Help

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

he / latest9.9 / hen / csource / api / Saxon.Api / Destination.cs @ a2e6e9df

1
using System;
2
using System.IO;
3
using System.Xml;
4
using JConfiguration = net.sf.saxon.Configuration;
5
using JPipelineConfiguration = net.sf.saxon.@event.PipelineConfiguration;
6
using JReceiver = net.sf.saxon.@event.Receiver;
7
using JProperties = java.util.Properties;
8
using JCharSequence = java.lang.CharSequence;
9
using JXPathException = net.sf.saxon.trans.XPathException;
10
using JCharacterMapIndex = net.sf.saxon.serialize.CharacterMapIndex;
11
using JSchemaType = net.sf.saxon.type.SchemaType;
12
using JLocation = net.sf.saxon.expr.parser.Location;
13
using JProxyReceiver = net.sf.saxon.@event.ProxyReceiver;
14
using JNodeName = net.sf.saxon.om.NodeName;
15
using JItem = net.sf.saxon.om.Item;
16
using JNodeInfo = net.sf.saxon.om.NodeInfo;
17
using JDotNetDomBuilder = net.sf.saxon.dotnet.DotNetDomBuilder;
18
using JDotNetOutputStream = net.sf.saxon.dotnet.DotNetOutputStream;
19
using JDotNetWriter = net.sf.saxon.dotnet.DotNetWriter;
20
using JDotNetReceiver = net.sf.saxon.dotnet.DotNetReceiver;
21
using JSerializationProperties = net.sf.saxon.serialize.SerializationProperties;
22
using JDestination = net.sf.saxon.s9api.Destination;
23
using JAbstractDestination = net.sf.saxon.s9api.AbstractDestination;
24
using JAction = net.sf.saxon.s9api.Action;
25
using java.net;
26
using net.sf.saxon.@event;
27
using net.sf.saxon.s9api;
28
using net.sf.saxon.serialize;
29

    
30
namespace Saxon.Api
31
{
32

    
33

    
34

    
35
    /// <summary>
36
    /// An abstract destination for the results of a query or transformation
37
    /// </summary>
38
    /// <remarks>
39
    /// </remarks>
40

    
41

    
42
    public interface XmlDestination
43
    {
44

    
45
        /// <summary>
46
        /// The underlying <c>Destination</c> object in the Saxon implementation
47
        /// </summary>
48
        /// <remarks>
49
        /// <para>This property provides access to internal methods in the Saxon engine that are
50
        /// not specifically exposed in the .NET API. In general these methods should be
51
        /// considered to be less stable than the classes in the Saxon.Api namespace.</para> 
52
        /// <para>The internal methods follow
53
        /// Java naming conventions rather than .NET conventions.</para>
54
		/// <para>Information about the returned <see cref="net.sf.saxon.Configuration"/> object 
55
		/// (and the objects it provides access to) is included in the Saxon JavaDoc docmentation.
56
        /// </para>
57
        /// </remarks>
58
        /// <returns>returns the underlying Destination object</returns>
59
		/**public**/ JDestination GetUnderlyingDestination();
60

    
61
    }
62

    
63
  
64

    
65
    /// <summary>
66
    /// A <c>Serializer</c> takes a tree representation of XML and turns
67
    /// it into lexical XML markup.
68
    /// </summary>
69
    /// <remarks>
70
    /// Note that this is serialization in the sense of the W3C XSLT and XQuery specifications.
71
    /// Unlike the class <c>System.Xml.Serialization.XmlSerializer</c>, this object does not
72
    /// serialize arbitrary CLI objects.
73
    /// </remarks>
74

    
75
    public class Serializer : XmlDestination
76
    {
77

    
78
        private net.sf.saxon.s9api.Serializer serializer;
79
        private JProperties props = new JProperties();
80
		private JCharacterMapIndex characterMap;
81
		private JProperties defaultOutputProperties = null;
82
        private Processor processor = null;
83
        private JConfiguration config = null; // Beware: this will often be null
84

    
85
        /// <summary>QName identifying the serialization parameter "method". If the method
86
        /// is a user-defined method, then it is given as a QName in Clark notation, that is
87
        /// "{uri}local".</summary>
88

    
89
        public static readonly QName METHOD =
90
            new QName("", "method");
91

    
92
        /// <summary>QName identifying the serialization parameter "byte-order-mark"</summary>
93

    
94
        public static readonly QName BYTE_ORDER_MARK =
95
            new QName("", "byte-order-mark");
96

    
97
        /// <summary>QName identifying the serialization parameter "cdata-section-elements".
98
        /// The value of this parameter is given as a space-separated list of expanded QNames in
99
        /// Clark notation, that is "{uri}local".</summary>
100

    
101
        public static readonly QName CDATA_SECTION_ELEMENTS =
102
            new QName("", "cdata-section-elements");
103

    
104
        /// <summary>QName identifying the serialization parameter "doctype-public"</summary>
105

    
106
        public static readonly QName DOCTYPE_PUBLIC =
107
            new QName("", "doctype-public");
108

    
109
        /// <summary>QName identifying the serialization parameter "doctype-system"</summary>
110

    
111
        public static readonly QName DOCTYPE_SYSTEM =
112
            new QName("", "doctype-system");
113

    
114
        /// <summary>QName identifying the serialization parameter "encoding"</summary>
115

    
116
        public static readonly QName ENCODING =
117
            new QName("", "encoding");
118

    
119
        /// <summary>QName identifying the serialization parameter "escape-uri-attributes".
120
        /// The value is the string "yes" or "no".</summary>
121

    
122
        public static readonly QName ESCAPE_URI_ATTRIBUTES =
123
            new QName("", "escape-uri-attributes");
124

    
125

    
126
        /// <summary>QName identifying the serialization parameter "include-content-type".
127
        /// The value is the string "yes" or "no".</summary>
128

    
129
        public static readonly QName INCLUDE_CONTENT_TYPE =
130
            new QName("", "include-content-type");
131

    
132
        /// <summary>QName identifying the serialization parameter "indent".
133
        /// The value is the string "yes" or "no".</summary>
134

    
135
        public static readonly QName INDENT =
136
            new QName("", "indent");
137

    
138
        /// <summary>QName identifying the serialization parameter "media-type".</summary>
139

    
140
        public static readonly QName MEDIA_TYPE =
141
            new QName("", "media-type");
142

    
143
        /// <summary>QName identifying the serialization parameter "normalization-form"</summary>
144

    
145
        public static readonly QName NORMALIZATION_FORM =
146
            new QName("", "normalization-form");
147

    
148
        /// <summary>
149
        /// Set to a string used to separate adjacent items in an XQuery result sequence
150
        /// </summary>
151
        public static readonly QName ITEM_SEPARATOR =
152
            new QName("", "item-separator");
153

    
154

    
155
        /// <summary>
156
        /// HTML version number
157
        /// </summary>
158
        public static readonly QName HTML_VERSION =
159
            new QName("" , "html-version");
160

    
161

    
162
        /// <summary>
163
        /// Build-tree option (XSLT only)
164
        /// </summary>
165
        public static readonly QName BUILD_TREE =
166
            new QName("", "build-tree");
167

    
168
        /// <summary>QName identifying the serialization parameter "omit-xml-declaration".
169
        /// The value is the string "yes" or "no".</summary>
170

    
171
        public static readonly QName OMIT_XML_DECLARATION =
172
            new QName("", "omit-xml-declaration");
173

    
174
        /// <summary>QName identifying the serialization parameter "standalone".
175
        /// The value is the string "yes" or "no" or "omit".</summary>
176

    
177
        public static readonly QName STANDALONE =
178
            new QName("", "standalone");
179

    
180
        /// <summary>QName identifying the serialization parameter "suppress-indentation"
181
        /// (introduced in XSLT/XQuery 3.0). Previously available as "saxon:suppress-indentation"
182
        /// The value is the string "yes" or "no" or "omit".</summary>
183

    
184
        public static readonly QName SUPPRESS_INDENTATION =
185
            new QName("", "suppress-indentation");
186

    
187
        /// <summary>QName identifying the serialization parameter "undeclare-prefixes".
188
        /// The value is the string "yes" or "no".</summary>
189

    
190
        public static readonly QName UNDECLARE_PREFIXES =
191
            new QName("", "undeclare-prefixes");
192

    
193
        /// <summary>QName identifying the serialization parameter "use-character-maps".
194
        /// This is available only with XSLT. The value of the parameter is a list of expanded QNames
195
        /// in Clark notation giving the names of character maps defined in the XSLT stylesheet.</summary>
196

    
197
        public static readonly QName USE_CHARACTER_MAPS =
198
            new QName("", "use-character-maps");
199

    
200
        /// <summary>QName identifying the serialization parameter "version"</summary>
201

    
202
        public static readonly QName VERSION =
203
            new QName("", "version");
204

    
205
        private static readonly String SAXON = NamespaceConstant.SAXON;
206

    
207

    
208
        /// <summary>QName identifying the serialization parameter "saxon:character-representation"</summary>
209

    
210

    
211
        public static readonly QName SAXON_CHARACTER_REPRESENTATION =
212
            new QName(SAXON, "saxon:character-representation");
213

    
214

    
215
        /// <summary>
216
        /// Saxon extension for use when writing to the text output method; this option causes the processing
217
        /// instructions hex and b64 to be recognized containing hexBinary or base64 data respectively.
218
        /// </summary>
219
        public static readonly QName SAXON_RECOGNIZE_BINARY =
220
            new QName("", "saxon:recognize-binary");
221

    
222
        /// <summary>QName identifying the serialization parameter "saxon:indent-spaces". The value
223
        /// is an integer (represented as a string) indicating the amount of indentation required.
224
        /// If specified, this parameter overrides indent="no".</summary>
225

    
226
        public static readonly QName SAXON_INDENT_SPACES =
227
            new QName(SAXON, "saxon:indent-spaces");
228

    
229

    
230
        /// <summary>
231
        /// Saxon extension: set to an integer (represented as a string) giving the desired maximum
232
        /// length of lines when indenting.Default is 80.
233
        /// </summary>
234
        public static readonly QName SAXON_LINE_LENGTH =
235
            new QName("", "saxon:line-length");
236

    
237

    
238
        /// <summary>
239
        /// Saxon extension: set to a space-separated list of attribute names, in Clark notation,
240
        /// indicating that attributes present in the list should be serialized in the order
241
        /// indicated, followed by attributes not present in the list(these are sorted first
242
        /// by namespace, then by local name).
243
        /// </summary>
244
        public static readonly QName SAXON_ATTRIBUTE_ORDER =
245
            new QName("", "saxon:attribute-order");
246

    
247
        /// <summary>
248
        ///  Saxon extension: request canonical XML output.
249
        /// </summary>
250
        public static readonly QName SAXON_CANONICAL =
251
            new QName("", "saxon:canonical");
252

    
253
        /// <summary>
254
        /// Saxon extension: set to any string. Indicates the sequence of characters used to represent
255
        /// a newline in the text output method, and in newlines used for indentation in any output
256
        /// methods that use indentation.
257
        /// </summary>
258
        public static readonly QName SAXON_NEWLINE =
259
            new QName("", "saxon:newline");
260

    
261

    
262
        /// <summary>
263
        /// Saxon extension for internal use: used in XSLT to tell the serializer whether the
264
        /// stylesheet used version="1.0" or version = "2.0"
265
        /// </summary>
266
        public static readonly QName SAXON_STYLESHEET_VERSION =
267
            new QName("", "saxon:stylesheet-version");
268

    
269
        /// <summary>QName identifying the serialization parameter "saxon:double-space". The value of this 
270
        /// parameter is given as a space-separated list of expanded QNames in Clark notation, that is 
271
        /// "{uri}local"; each QName identifies an element that should be preceded by an extra blank line within
272
        /// indented output.</summary>
273

    
274
        public static readonly QName SAXON_DOUBLE_SPACE =
275
            new QName(SAXON, "saxon:double-space");
276

    
277
        /// <summary>QName identifying the serialization parameter "suppress-indentation". Retained
278
        /// as a synonym of SUPPRESS_INDENTATION for backwards compatibility.</summary>
279

    
280
        public static readonly QName SAXON_SUPPRESS_INDENTATION = SUPPRESS_INDENTATION;
281

    
282
        /// <summary>QName identifying the serialization parameter "saxon:next-in-chain". This
283
        /// is available only with XSLT, and identifies the URI of a stylesheet that is to be used to
284
        /// process the results before passing them to their final destination.</summary>
285

    
286
        public static readonly QName NEXT_IN_CHAIN =
287
            new QName(SAXON, "saxon:next-in-chain");
288

    
289
        /// <summary>QName identifying the serialization parameter "saxon:require-well-formed". The
290
        /// value is the string "yes" or "no". If set to "yes", the output must be a well-formed
291
        /// document, or an error will be reported. ("Well-formed" here means that the document node
292
        /// must have exactly one element child, and no text node children other than whitespace-only
293
        /// text nodes).</summary>
294

    
295
        public static readonly QName SAXON_REQUIRE_WELL_FORMED =
296
            new QName(SAXON, "saxon:require-well-formed");
297

    
298

    
299
        /// <summary>
300
        /// Saxon extension for interfacing with debuggers; indicates that the location information is
301
        /// available for events in this output stream
302
        /// </summary>
303
        public static readonly QName SUPPLY_SOURCE_LOCATOR =
304
            new QName("", "supply-source-locator");
305

    
306

    
307
        /// <summary>
308
        /// Saxon extension, indicates that the output of a query is to be wrapped before serialization,
309
        /// such that each item in the result sequence is enclosed in an element indicating its type
310
        /// </summary>
311
        public static readonly QName SAXON_WRAP =
312
            new QName("", "", "wrap-result-sequence");
313

    
314
        /// <summary>Create a Serializer</summary>
315

    
316
        internal Serializer(net.sf.saxon.s9api.Serializer s)
317
        {
318
            serializer = s;
319
        }
320

    
321
        /// <summary>Set a serialization property</summary>
322
        /// <remarks>In the case of XSLT, properties set within the serializer override
323
        /// any properties set in <c>xsl:output</c> declarations in the stylesheet.
324
        /// Similarly, with XQuery, they override any properties set in the Query
325
        /// prolog using <c>declare option saxon:output</c>.</remarks>
326
        /// <example>
327
        ///   <code>
328
        ///     Serializer qout = new Serializer();
329
        ///     qout.SetOutputProperty(Serializer.METHOD, "xml");
330
        ///     qout.SetOutputProperty(Serializer.INDENT, "yes");
331
        ///     qout.SetOutputProperty(Serializer.SAXON_INDENT_SPACES, "1");
332
        ///   </code>
333
        /// </example> 
334
        /// <param name="name">The name of the serialization property to be set</param>
335
        /// <param name="value">The value to be set for the serialization property. May be null
336
        /// to unset the property (that is, to set it back to the default value).</param>
337

    
338
        public void SetOutputProperty(QName name, String value)
339
        {
340
           props.setProperty(name.ClarkName, value);
341
           serializer.setOutputProperty(net.sf.saxon.s9api.Serializer.getProperty(name.UnderlyingQName()), value);
342
        }
343

    
344
        /// <summary>
345
		/// Set default output properties, for use when no explicit properties are set using <c>SetOutputProperty()</c>.
346
        /// The values supplied are typically those specified in the stylesheet or query. In the case of XSLT,
347
        /// they are the properties associated with unamed <c>xsl:output</c> declarations.
348
        /// </summary>
349
        /// <param name="props"></param>
350

    
351
		public void SetDefaultOutputProperties(JProperties props)
352
		{
353
			this.defaultOutputProperties = props;
354
		}
355

    
356
        /// <summary>
357
        /// Get a character map
358
        /// </summary>
359
        
360
		public JCharacterMapIndex GetCharacterMap()
361
        {
362
            return this.characterMap;
363
        }
364

    
365
        /// <summary>
366
        /// Set a character map to be used
367
        /// </summary>
368
        /// <param name="charMap">the character map</param>
369

    
370
		public void SetCharacterMap(JCharacterMapIndex charMap)
371
		{
372
			this.characterMap = charMap;
373
		}
374
			
375

    
376
        /// <summary>Specify the destination of the serialized output, in the
377
        /// form of a file name</summary>
378
        /// <param name="filename">The name of the file to receive the serialized output. This
379
        /// method sets the destination base URI to the URI corresponding to the name of the supplied file.</param>
380
		/// <exception cref="DynamicError">Throws a <c>DynamicError</c> if it is not possible to 
381
		/// create an output stream to write to this file, for example, if the filename is in a
382
        /// directory that does not exist.</exception>
383

    
384
        public void SetOutputFile(String filename)
385
        {
386
            try
387
            {
388
                serializer.setOutputFile(new java.io.File(filename));
389
            }
390
            catch (java.io.IOException err)
391
            {
392
                JXPathException e = new JXPathException(err);
393
                throw new DynamicError(e);
394
            }
395
        }
396

    
397

    
398
        /// <summary>Specify the destination of the serialized output, in the
399
        /// form of a <c>Stream</c>.</summary>
400
        /// <remarks>Saxon will not close the stream on completion; this is the
401
        /// caller's responsibility.</remarks>
402
        /// <param name="stream">The stream to which the output will be written.
403
        /// This must be a stream that allows writing.</param>
404

    
405
        public void SetOutputStream(Stream stream)
406
        {
407

    
408
            serializer.setOutputStream(new JDotNetOutputStream(stream));
409
        }
410
			
411
    	/// <summary>Get the current output destination.</summary> 
412
		/// <returns>an <c>OutputStream</c>, <c>Writer</c>, or <c>File</c>, depending on the previous calls to
413
		/// <c>SetOutputstream</c>, <c>SetOutputWriter</c>, or <c>SetOutputFile</c>; or null, if no output destintion has
414
        /// been set up.</returns>
415

    
416
		public object GetOutputDestination(){
417
			return serializer.getOutputDestination();		
418
		}
419

    
420

    
421
		/// <summary>Set the <c>Processor</c> associated with this <c>Serializer</c>. This will be called automatically if the
422
		/// serializer is created using one of the <c>Processor.NewSerializer()</c> methods.</summary>
423
		/// <param name="processor"> the associated <c>Processor</c></param>
424
        
425
        public void SetProcessor(Processor processor)
426
        {
427
            this.processor = processor;
428
            this.config = processor.Implementation;
429
        }
430

    
431
        /// <summary>Specify the destination of the serialized output, in the
432
        /// form of a <c>TextWriter</c>.</summary>
433
        /// <remarks>Note that when writing to a <c>TextWriter</c>, character encoding is
434
        /// the responsibility of the <c>TextWriter</c>, not the <c>Serializer</c>. This
435
        /// means that the encoding requested in the output properties is ignored; it also
436
        /// means that characters that cannot be represented in the target encoding will
437
        /// use whatever fallback representation the <c>TextWriter</c> defines, rather than
438
        /// being represented as XML character references.</remarks>
439
        /// <param name="textWriter">The stream to which the output will be written.
440
        /// This must be a stream that allows writing. Saxon will not close the
441
        /// <c>TextWriter</c> on completion; this is the caller's responsibility.</param>
442

    
443
        public void SetOutputWriter(TextWriter textWriter)
444
        {
445
            serializer.setOutputWriter(new JDotNetWriter(textWriter));
446
        }
447

    
448

    
449
        /// <summary>
450
		/// Serialize an <c>XdmNode</c> to the selected output destination using this serializer.
451
        /// </summary>
452
        /// <param name="node">The node to be serialized</param>
453
        /// <remarks>since 9.8</remarks>
454
        public void SerializeXdmNode(XdmNode node)
455
        {
456
            serializer.serializeNode((net.sf.saxon.s9api.XdmNode)XdmValue.FromGroundedValueToJXdmValue(node.value));
457
        }
458

    
459

    
460
        /// <summary>
461
		/// Serialize an arbitary <c>XdmValue</c> to the selected output destination using this serializer.
462
        /// The supplied sequence is first wrapped in a document node according to the rules given in section 2
463
		/// (Sequence Normalization) of the XSLT/XQuery serialization specification; the resulting document node 
464
		/// is then serialized using the serialization parameters defined in this serializer. A call on this 
465
		/// method will close the writer or output stream internally.
466
        /// </summary>
467
        /// <param name="value"> The value to be serialized</param>
468
        /// <remarks>since 9.8</remarks>
469
        public void SerializeXdmValue(XdmValue value) {
470

    
471

    
472
            
473
            if (value is XdmNode)
474
            {
475
                SerializeXdmNode((XdmNode)value);  
476
            }
477
            else {
478
                serializer.serializeXdmValue(net.sf.saxon.s9api.XdmValue.wrap(value.Unwrap()));
479
            }
480

    
481
        }
482

    
483
        
484
        /// <summary>
485
        /// Close any resources associated with this destination. Note that this does <b>not</b>
486
        /// close any user-supplied OutputStream or Writer; those must be closed explicitly
487
        /// by the calling application.
488
        /// </summary>
489
        public void Close()
490
        {
491
            serializer.close();
492
        }
493

    
494

    
495
        /// <summary>
496
        /// The underlying <c>Destination</c> object in the Saxon implementation
497
        /// </summary>
498
        /// <remarks>
499
        /// <para>This property provides access to internal methods in the Saxon engine that are
500
        /// not specifically exposed in the .NET API. In general these methods should be
501
        /// considered to be less stable than the classes in the Saxon.Api namespace.</para> 
502
        /// <para>The internal methods follow
503
        /// Java naming conventions rather than .NET conventions.</para>
504
        /// <para>Information about the returned <see cref="net.sf.saxon.Configuration"/> object 
505
        /// (and the objects it provides access to) is included in the Saxon JavaDoc docmentation.
506
        /// </para>
507
        /// </remarks>
508
        /// <returns>returns the underlying Destination object</returns>
509
        public JDestination GetUnderlyingDestination()
510
        {
511
            return serializer;
512
        }
513

    
514

    
515
        /// <summary>
516
        /// Close the destination and notify all registered listeners that it has been closed.
517
        /// This method is intended for internal use by Saxon. The method first calls
518
		/// <see cref="Close"/> to close the destination, then it calls <c>java.util.function.Consumer.accept()</c> 
519
		/// on each of the listeners in turn to notify the fact that it has been closed.
520
        /// </summary>
521
        public void CloseAndNotify()
522
        {
523
            try
524
            {
525
                serializer.closeAndNotify();
526
            }
527
            catch (net.sf.saxon.s9api.SaxonApiException exception) {
528
                throw new StaticError(exception);
529
            }
530
        }
531

    
532

    
533
        /// <summary>This property determines the base Uri of the constructed <c>Serializer</c>. 
534
        /// </summary>
535

    
536
        public Uri BaseUri
537
        {
538
            get { return new Uri(serializer.getDestinationBaseURI().toASCIIString()); }
539
            set { serializer.setDestinationBaseURI(new java.net.URI(value.ToString())); }
540
        }
541

    
542

    
543

    
544
    }
545

    
546
    /// <summary>
547
	/// A <c>DomDestination</c> represents an <c>XmlDocument</c> that is constructed to hold the
548
    /// output of a query or transformation.
549
    /// </summary>
550
    /// <remarks>
551
    /// No data needs to be supplied to the <c>DomDestination</c> object. The query or transformation
552
    /// populates an <c>XmlDocument</c>, which may then be retrieved as the value of the <c>XmlDocument</c>
553
    /// property.
554
    /// </remarks>
555

    
556
    public class DomDestination : XmlDestination
557
    {
558

    
559
        internal JDotNetDomBuilder builder;
560
        internal net.sf.saxon.dotnet.DotNetDomDestination destination;
561

    
562
        /// <summary>Construct a <c>DomDestination</c>.</summary>
563
        /// <remarks>With this constructor, the system will create a new DOM Document
564
        /// to act as the destination of the query or transformation results. The document
565
		/// node of the new document may be retrieved via the <c>XmlDocument</c> property.</remarks>
566

    
567
        public DomDestination()
568
        {
569
            builder = new JDotNetDomBuilder();
570
            destination = new net.sf.saxon.dotnet.DotNetDomDestination(builder);
571
        }
572

    
573
        /// <summary>Construct a <c>DomDestination</c> based on an existing document node.</summary>
574
        /// <remarks>The new data will be added as a child of the supplied node.</remarks>
575
        /// <param name="attachmentPoint">The document node to which new contents will
576
        /// be attached. To ensure that the new document is well-formed, this document node
577
        /// should have no existing children.</param>
578

    
579
        public DomDestination(XmlDocument attachmentPoint)
580
        {
581
            builder = new JDotNetDomBuilder();
582
            builder.setAttachmentPoint(attachmentPoint);
583
        }
584

    
585
        /// <summary>Construct a <c>DomDestination</c> based on an existing document fragment node.</summary>
586
        /// <remarks>The new data will be added as a child of the supplied node.</remarks>
587
        /// <param name="attachmentPoint">The document fragment node to which new contents will
588
        /// be attached. The new contents will be added after any existing children.</param>
589

    
590
        public DomDestination(XmlDocumentFragment attachmentPoint)
591
        {
592
            builder = new JDotNetDomBuilder();
593
            builder.setAttachmentPoint(attachmentPoint);
594
        }
595

    
596
        /// <summary>Construct a <c>DomDestination</c> based on an existing element node.</summary>
597
        /// <remarks>The new data will be added as a child of the supplied element node.</remarks>
598
        /// <param name="attachmentPoint">The element node to which new contents will
599
        /// be attached. The new contents will be added after any existing children.</param>
600

    
601
        public DomDestination(XmlElement attachmentPoint)
602
        {
603
            builder = new JDotNetDomBuilder();
604
            builder.setAttachmentPoint(attachmentPoint);
605
        }
606

    
607
        /// <summary>After construction, retrieve the constructed document node.</summary>
608
        /// <remarks>If the zero-argument constructor was used, this will be a newly
609
        /// constructed document node. If the constructor supplied a document node, the
610
        /// same document node will be returned. If the constructor supplied a document fragment
611
        /// node or an element node, this method returns the <c>OwnerDocument</c> property of 
612
        /// that node.</remarks>
613

    
614
        public XmlDocument XmlDocument
615
        {
616
            get { return builder.getDocumentNode(); }
617
        }
618

    
619

    
620
        /// <summary>
621
        /// Close any resources associated with this destination. Note that this does <b>not</b>
622
        /// close any user-supplied OutputStream or Writer; those must be closed explicitly
623
        /// by the calling application.
624
        /// </summary>
625
        public void Close()
626
        {
627
            builder.close();
628
        }
629

    
630

    
631

    
632
        /// <summary>
633
        /// The underlying <c>Destination</c> object in the Saxon implementation
634
        /// </summary>
635
        /// <remarks>
636
        /// <para>This property provides access to internal methods in the Saxon engine that are
637
        /// not specifically exposed in the .NET API. In general these methods should be
638
        /// considered to be less stable than the classes in the Saxon.Api namespace.</para> 
639
        /// <para>The internal methods follow
640
        /// Java naming conventions rather than .NET conventions.</para>
641
        /// <para>Information about the returned <see cref="net.sf.saxon.Configuration"/> object 
642
        /// (and the objects it provides access to) is included in the Saxon JavaDoc docmentation.
643
        /// </para>
644
        /// </remarks>
645
        /// <returns>returns the underlying Destination object</returns>
646
        public JDestination GetUnderlyingDestination()
647
        {
648
            return destination;
649
        }
650

    
651

    
652
	}
653

    
654
	/// <summary>
655
	/// A <c>RawDestination</c> is an <c>Destination</c> that accepts a sequence output
656
	/// by a stylesheet or query and returns it directly as an <c>XdmValue</c>, without
657
	/// constructing an XML tree, and without serialization. It corresponds to the serialization
658
	/// option <code>build-tree="no"</code>.
659
	/// </summary>
660

    
661
    public class RawDestination : XmlDestination
662

    
663
    {
664

    
665
        internal net.sf.saxon.s9api.RawDestination destination;
666

    
667
        /// <summary>Construct a <c>RawDestination</c></summary>
668

    
669
        public RawDestination()
670
        {
671
            destination = new net.sf.saxon.s9api.RawDestination();
672
        }
673

    
674
        /// <summary>
675
        /// The underlying <c>Destination</c> object in the Saxon implementation
676
        /// </summary>
677
        /// <remarks>
678
        /// <para>This property provides access to internal methods in the Saxon engine that are
679
        /// not specifically exposed in the .NET API. In general these methods should be
680
        /// considered to be less stable than the classes in the Saxon.Api namespace.</para> 
681
        /// <para>The internal methods follow
682
        /// Java naming conventions rather than .NET conventions.</para>
683
        /// <para>Information about the returned <see cref="net.sf.saxon.Configuration"/> object 
684
        /// (and the objects it provides access to) is included in the Saxon JavaDoc docmentation.
685
        /// </para>
686
        /// </remarks>
687
        /// <returns>returns the underlying Destination object</returns>
688
        public JDestination GetUnderlyingDestination()
689
        {
690
            return destination;
691
        }
692

    
693
        /// <summary>
694
        /// Close the destination and notify all registered listeners that it has been closed.
695
        /// This method is intended for internal use by Saxon. The method first calls
696
		/// <see cref="Close"/> to close the destination, then it calls <c>java.util.function.Consumer.accept()</c>
697
		/// on each of the listeners in turn to notify the fact that it has been closed.
698
        /// </summary>
699
        public void CloseAndNotify()
700
        {
701
            destination.closeAndNotify();
702
        }
703

    
704

    
705

    
706
        /// <summary>This property determines the base URI of the constructed <c>XdmNode</c>. 
707
        /// If the <c>BaseUri</c> property of the <c>XdmDestination</c> is set before the destination is written to,
708
        /// then the constructed <c>XdmNode</c> will have this base URI. Setting this property after constructing the node
709
        /// has no effect.
710
        /// </summary>
711

    
712
        public Uri BaseUri
713
        {
714
            get { return new Uri(destination.getDestinationBaseURI().toASCIIString()); }
715
            set { destination.setDestinationBaseURI(new java.net.URI(value.ToString())); }
716
        }
717

    
718

    
719
        /// <summary>
720
        /// Close any resources associated with this destination. Note that this does <b>not</b>
721
        /// close any user-supplied OutputStream or Writer; those must be closed explicitly
722
        /// by the calling application.
723
        /// </summary>
724
        public void Close()
725
        {
726
            destination.close();
727
        }
728

    
729
        /// <summary>After construction, retrieve the constructed document node.</summary>
730
        /// <remarks>
731
        /// <para>The value of the property will be null if no data has been written to the
732
        /// <c>RawDestination</c>, either because the process that writes to the destination has not
733
        /// yet been run, or because the process produced no output.</para>
734
        /// </remarks>
735

    
736
        public XdmValue XdmValue
737
        {
738
            get
739
            {
740
                net.sf.saxon.om.GroundedValue value = destination.getXdmValue().getUnderlyingValue();
741
                return (value == null ? null : XdmValue.Wrap(value));
742
            }
743
        }
744
    }
745

    
746
    /// <summary>
747
	/// A <c>NullDestination</c> is an <c>XmlDestination</c> that discards all its output.
748
    /// </summary>
749

    
750
    public class NullDestination : XmlDestination
751
    {
752

    
753
        net.sf.saxon.s9api.NullDestination destination;
754
        /// <summary>Construct a <c>NullDestination</c></summary>
755

    
756
        public NullDestination()
757
        {
758
            destination = new net.sf.saxon.s9api.NullDestination();
759
        }
760

    
761
        /// <summary>This property determines the base Uri of the constructed <c>Serializer</c>. 
762
        /// </summary>
763

    
764
        public Uri BaseUri
765
        {
766
            get { return new Uri(destination.getDestinationBaseURI().toASCIIString()); }
767
            set { destination.setDestinationBaseURI(new java.net.URI(value.ToString())); }
768
        }
769

    
770

    
771
        /// <summary>
772
        /// The underlying <c>Destination</c> object in the Saxon implementation, which in the NullDestination is null.
773
        /// </summary>
774
        /// <returns>returns null</returns>
775
        public JDestination GetUnderlyingDestination()
776
        {
777
            return destination;
778
        }
779

    
780
    }
781

    
782

    
783
    /// <summary>
784
    /// A <c>TextWriterDestination</c> is an implementation of <c>XmlDestination</c> that wraps
785
    /// an instance of <c>XmlWriter</c>.
786
    /// </summary>
787
    /// <remarks>
788
    /// <para>The name <c>TextWriterDestination</c> is a misnomer; originally this class would
789
    /// only wrap an <c>XmlTextWriter</c>. It will now wrap any <c>XmlWriter</c>.</para>
790
    /// <para>Note that when a <c>TextWriterDestination</c> is used to process the output of a stylesheet
791
    /// or query, the output format depends only on the way the underlying <c>XmlWriter</c>
792
    /// is configured; serialization parameters present in the stylesheet or query are ignored.
793
    /// The XSLT <c>disable-output-escaping</c> option is also ignored. If serialization
794
    /// is to be controlled from the stylesheet or query, use a <c>Serializer</c> as the
795
    /// <c>Destination</c>.</para>
796
    /// </remarks>
797

    
798
    public class TextWriterDestination : JAbstractDestination, XmlDestination
799
    {
800

    
801
        internal XmlWriter writer;
802
        internal bool closeAfterUse = true;
803

    
804
		/// <summary>Construct a <c>TextWriterDestination</c></summary>
805
        /// <param name="writer">The <c>XmlWriter</c> that is to be notified of the events
806
        /// representing the XML document.</param>
807

    
808
        public TextWriterDestination(XmlWriter writer)
809
        {
810
            this.writer = writer;
811
        }
812

    
813
        /// <summary>
814
        /// The <c>CloseAfterUse</c> property indicates whether the underlying <c>XmlWriter</c> is closed
815
        /// (by calling its <c>Close()</c> method) when Saxon has finished writing to it. The default
816
        /// value is true, in which case <c>Close()</c> is called. If the property is set to <c>false</c>,
817
        /// Saxon will refrain from calling the <c>Close()</c> method, and merely call <c>Flush()</c>,
818
        /// which can be useful if further output is to be written to the <c>XmlWriter</c> by the application.
819
        /// </summary>
820

    
821
        public bool CloseAfterUse
822
        {
823
            get { return closeAfterUse; }
824
            set { closeAfterUse = value; }
825
        }
826

    
827
        /// <summary>
828
        /// Close any resources associated with this destination. Note that this does <b>not</b>
829
        /// close any user-supplied OutputStream or Writer; those must be closed explicitly
830
        /// by the calling application.
831
        /// </summary>
832
        public override void close()
833
        {
834
            writer.Close();
835
        }
836

    
837

    
838
        /// <summary>
839
		/// Return a <c>Receiver</c>. Saxon calls this method to obtain a Java <c>Receiver</c>, to which it then sends
840
        /// a sequence of events representing the content of an XML document. The method is intended
841
        /// primarily for internal use, and may give poor diagnostics if used incorrectly.
842
        /// </summary>
843
        /// <returns>The receiver</returns>
844
		/// <param name="pipe">The Saxon configuration as a <c>JPipelineConfiguration</c>. 
845
		/// This is supplied so that the destination can
846
        /// use information from the configuration (for example, a reference to the name pool)
847
		/// to construct or configure the returned <c>Receiver</c>.</param>
848
        
849
		public JReceiver GetReceiver(JPipelineConfiguration pipe, JSerializationProperties params1)
850
        {
851
            JDotNetReceiver dnr = new JDotNetReceiver(writer);
852
			dnr.setPipelineConfiguration (pipe);
853
            dnr.setCloseAfterUse(closeAfterUse);
854
            return params1.makeSequenceNormalizer(dnr);
855
        }
856

    
857
        /// <summary>
858
		/// Return a <c>Receiver</c>. Saxon calls this method to obtain a Java <c>Receiver</c>, to which it then sends
859
        /// a sequence of events representing the content of an XML document. The method is intended
860
        /// primarily for internal use, and may give poor diagnostics if used incorrectly.
861
        /// </summary>
862
        /// <returns>The receiver</returns>
863
		/// <param name="pipe">The Saxon configuration as a <c>JPipelineConfiguration</c>. 
864
		/// This is supplied so that the destination can
865
        /// use information from the configuration (for example, a reference to the name pool)
866
		/// to construct or configure the returned <c>Receiver</c>.</param>
867
        public override JReceiver getReceiver(JPipelineConfiguration pipe, JSerializationProperties value2)
868
        {
869
            return GetReceiver(pipe, value2);
870
        }
871

    
872
        /// <summary>
873
        /// The underlying <c>Destination</c> object in the Saxon implementation
874
        /// </summary>
875
        /// <remarks>
876
        /// <para>This property provides access to internal methods in the Saxon engine that are
877
        /// not specifically exposed in the .NET API. In general these methods should be
878
        /// considered to be less stable than the classes in the Saxon.Api namespace.</para> 
879
        /// <para>The internal methods follow
880
        /// Java naming conventions rather than .NET conventions.</para>
881
        /// <para>Information about the returned <see cref="net.sf.saxon.Configuration"/> object 
882
        /// (and the objects it provides access to) is included in the Saxon JavaDoc docmentation.
883
        /// </para>
884
        /// </remarks>
885
        /// <returns>returns the underlying Destination object</returns>
886
        public JDestination GetUnderlyingDestination()
887
        {
888
            return this;
889
        }
890
    }
891

    
892

    
893
    /// <summary>
894
    /// An <c>XdmDestination</c> is an <c>XmlDestination</c> in which an <c>XdmNode</c> 
895
    /// is constructed to hold the output of a query or transformation: 
896
    /// that is, a tree using Saxon's implementation of the XDM data model.
897
    /// </summary>
898
    /// <remarks>
899
    /// <para>No data needs to be supplied to the <c>XdmDestination</c> object. The query or transformation
900
    /// populates an <c>XmlNode</c>, which may then be retrieved as the value of the <c>XmlNode</c>
901
    /// property.</para>
902
    /// <para>An <c>XdmDestination</c> can be reused to hold the results of a second transformation only
903
    /// if the <c>Reset</c> method is first called to reset its state.</para>
904
    /// </remarks>
905

    
906
    public class XdmDestination : XmlDestination
907
    {
908
        internal net.sf.saxon.s9api.XdmDestination destination;
909

    
910
        /// <summary>Construct an <c>XdmDestination</c></summary>
911

    
912
        public XdmDestination()
913
        {
914
            destination = new net.sf.saxon.s9api.XdmDestination();
915
        }
916

    
917
        ///<summary>
918
        /// The Tree Model implementation to be used for the constructed document. By default
919
		/// the <c>TinyTree</c> is used. The main reason for using the <c>LinkedTree</c> alternative is if
920
		/// updating is required (the <c>TinyTree</c> is not updateable).
921
        ///</summary>
922

    
923
        public TreeModel TreeModel
924
        {
925
            get
926
            {
927
                return  (TreeModel)destination.getTreeModel().getSymbolicValue();
928
            }
929
            set
930
            {
931
                destination.setTreeModel(net.sf.saxon.om.TreeModel.getTreeModel((int)value));
932
            }
933
        }
934

    
935
		/// <summary>This property determines the base URI of the constructed <c>XdmNode</c>. 
936
		/// If the <c>BaseUri</c> property of the <c>XdmDestination</c> is set before the destination is written to,
937
		/// then the constructed <c>XdmNode</c> will have this base URI. Setting this property after constructing the node
938
        /// has no effect.
939
        /// </summary>
940

    
941
        public Uri BaseUri
942
        {
943
            get { return new Uri(destination.getBaseURI().toASCIIString()); }
944
            set { destination.setBaseURI(new java.net.URI(value.ToString())); }
945
        }
946

    
947

    
948
        /// <summary>Reset the state of the <c>XdmDestination</c> so that it can be used to hold
949
        /// the result of another query or transformation.</summary>
950

    
951
        public void Reset()
952
        {
953
            destination.reset();
954
        }
955

    
956
        /// <summary>After construction, retrieve the constructed document node.</summary>
957
        /// <remarks>
958
        /// <para>The value of the property will be null if no data has been written to the
959
		/// <c>XdmDestination</c>, either because the process that writes to the destination has not
960
        /// yet been run, or because the process produced no output.</para>
961
        /// </remarks>
962

    
963
        public XdmNode XdmNode
964
        {
965
            get
966
            {
967
                JNodeInfo jnode = destination.getXdmNode().getUnderlyingNode();
968
                return (jnode == null ? null : (XdmNode)XdmValue.Wrap(jnode));
969
            }
970
        }
971

    
972

    
973
        /// <summary>
974
		/// Get the underlying Saxon <c>Destination</c> object from the <c>XdmDestination</c>.
975
        /// This method is for internal use but is provided for the benefit of applications that need to mix
976
        /// use of the Saxon .NET API with direct use of the underlying objects
977
        /// and methods offered by the Java implementation.
978
        /// </summary>
979
        public JDestination GetUnderlyingDestination()
980
        {
981
            return destination;
982
        }
983

    
984
        public void closeAndNotify()
985
        {
986
            destination.closeAndNotify();
987
        }
988

    
989

    
990
        /// <summary>
991
        /// Set the base URI of the resource being written to this destination
992
        /// </summary>
993
        /// <param name="uri">the base URI to be used</param>
994
        public void setDestinationBaseURI(java.net.URI uri)
995
        {
996
            destination.setDestinationBaseURI(uri);
997
        }
998

    
999
        /// <summary>
1000
        /// Get the base URI of the resource being written to this destination
1001
        /// </summary>
1002
        /// <returns>the base URI, or null if none is known</returns>
1003
        public java.net.URI getDestinationBaseURI()
1004
        {
1005
            return destination.getDestinationBaseURI();
1006
        }
1007

    
1008
        public void onClose(JAction a)
1009
        {
1010
            destination.onClose(a);
1011
        }
1012

    
1013
        /// <summary>
1014
        /// Close the destination, allowing resources to be released. Saxon calls this
1015
        /// method when it has finished writing to the destination.
1016
        /// </summary>
1017
        public void close()
1018
        {
1019
            destination.close();
1020
        }
1021

    
1022
        /// <summary>
1023
        /// <c>TreeProtector</c> is a filter that ensures that the events reaching the <c>Builder</c> constitute a single
1024
        /// tree rooted at an element or document node (because anything else will crash the builder)
1025
        /// </summary>
1026

    
1027
        public class TreeProtector : JProxyReceiver
1028
        {
1029

    
1030
            private int level = 0;
1031
            private bool ended = false;
1032

    
1033
            /// <summary>
1034
            /// Constructor
1035
            /// </summary>
1036
            /// <param name="next">Set the underlying receiver</param>
1037
            public TreeProtector(JReceiver next)
1038
                : base(next)
1039
            {
1040

    
1041
            }
1042

    
1043
            /// <summary>
1044
            /// Start of a document node
1045
            /// </summary>
1046
            /// <param name="properties"></param>
1047
            public override void startDocument(int properties)
1048
            {
1049
                if (ended)
1050
                {
1051
                    JXPathException e = new JXPathException("Only a single document can be written to an XdmDestination");
1052
                    throw new DynamicError(e);
1053
                }
1054
                base.startDocument(properties);
1055
                level++;
1056
            }
1057

    
1058
            /// <summary>
1059
            /// Notify the end of a document node
1060
            /// </summary>
1061
            public override void endDocument()
1062
            {
1063
                base.endDocument();
1064
                level--;
1065
                if (level == 0)
1066
                {
1067
                    ended = true;
1068
                }
1069
            }
1070

    
1071
            /// <summary>
1072
            /// Notify the start of an element
1073
            /// </summary>
1074
            /// <param name="nameCode"></param>
1075
            /// <param name="typeCode"></param>
1076
            /// <param name="location"></param>
1077
            /// <param name="properties"></param>
1078
            public override void startElement(JNodeName nameCode, JSchemaType typeCode, JLocation location, int properties)
1079
            {
1080
                if (ended)
1081
                {
1082
                    JXPathException e = new JXPathException("Only a single root node can be written to an XdmDestination");
1083
                    throw new DynamicError(e);
1084
                }
1085
                base.startElement(nameCode, typeCode, location, properties);
1086
                level++;
1087
            }
1088

    
1089
            /// <summary>
1090
            /// End of element
1091
            /// </summary>
1092
            public override void endElement()
1093
            {
1094
                base.endElement();
1095
                level--;
1096
                if (level == 0)
1097
                {
1098
                    ended = true;
1099
                }
1100
            }
1101

    
1102
            /// <summary>
1103
            /// Character data
1104
            /// </summary>
1105
            /// <param name="chars">Character data as input</param>
1106
            /// <param name="location">Provides information such as line number and system ID</param>
1107
            /// <param name="properties">Bit significant value. The following bits are defined</param>
1108
			public override void characters(JCharSequence chars, JLocation location, int properties)
1109
            {
1110
                if (level == 0)
1111
                {
1112
                    JXPathException e = new JXPathException("When writing to an XdmDestination, text nodes are only allowed within a document or element node");
1113
                    throw new DynamicError(e);
1114
                }
1115
                base.characters(chars, location, properties);
1116
            }
1117

    
1118
            /// <summary>
1119
            /// Processing instruction
1120
            /// </summary>
1121
            /// <param name="target">The PI name. This must be a legal name (it will not be checked)</param>
1122
            /// <param name="data">The data portion of the processing instruction</param>
1123
            /// <param name="location">provides information about the PI</param>
1124
            /// <param name="properties">Additional information about the PI</param>
1125
			public override void processingInstruction(String target, JCharSequence data, JLocation location, int properties)
1126
            {
1127
                if (level == 0)
1128
                {
1129
                    JXPathException e = new JXPathException("When writing to an XdmDestination, processing instructions are only allowed within a document or element node");
1130
                    throw new DynamicError(e);
1131
                }
1132
                base.processingInstruction(target, data, location, properties);
1133
            }
1134

    
1135
            /// <summary>
1136
            /// Output a comment
1137
            /// </summary>
1138
            /// <param name="chars">The content of the comment</param>
1139
            /// <param name="location">provides information such as line number and system ID</param>
1140
            /// <param name="properties">Additional information about the comment</param>
1141
			public override void comment(JCharSequence chars, JLocation location, int properties)
1142
            {
1143
                if (level == 0)
1144
                {
1145
                    JXPathException e = new JXPathException("When writing to an XdmDestination, comment nodes are only allowed within a document or element node");
1146
                }
1147
                base.comment(chars, location, properties);
1148
            }
1149

    
1150

    
1151
            /// <summary>
1152
            /// Append an  arbitrary item (node or atomic value) to the output
1153
            /// </summary>
1154
            /// <param name="item">the item to be appended</param>
1155
            /// <param name="location">the location of the calling instruction, for diagnostics</param>
1156
            /// <param name="copyNamespaces">if the item is an element node, this indicates whether its namespace need to be copied. 
1157
            /// 0x80000 means ALL_NAMESPACE, 0x40000 means LOCAL_NAMESPACE and 0 means no namespace</param>
1158
			public override void append(JItem item, JLocation location, int copyNamespaces)
1159
            {
1160
                if (level == 0)
1161
                {
1162
                    JXPathException e = new JXPathException("When writing to an XdmDestination, atomic values are only allowed within a document or element node");
1163
                }
1164
                base.append(item, location, copyNamespaces);
1165
            }
1166

    
1167
        }
1168
    }
1169

    
1170

    
1171
}
1172

    
1173
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1174
// Copyright (c) 2018 Saxonica Limited.
1175
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
1176
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
1177
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
1178
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
(2-2/13)