Project

Profile

Help

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

he / src / main / csharp / api / Saxon.Api / Destination.cs @ c7deb2a9

1
using System;
2
using System.IO;
3
using System.Xml;
4
using JConfiguration = net.sf.saxon.Configuration;
5
using JAttributeMap = net.sf.saxon.om.AttributeMap; 
6
using JPipelineConfiguration = net.sf.saxon.@event.PipelineConfiguration;
7
using JReceiver = net.sf.saxon.@event.Receiver;
8
using JProperties = java.util.Properties;
9
using JCharSequence = java.lang.CharSequence;
10
using JXPathException = net.sf.saxon.trans.XPathException;
11
using JCharacterMapIndex = net.sf.saxon.serialize.CharacterMapIndex;
12
using JSchemaType = net.sf.saxon.type.SchemaType;
13
using JLocation = net.sf.saxon.s9api.Location;
14
using JProxyReceiver = net.sf.saxon.@event.ProxyReceiver;
15
using JNodeName = net.sf.saxon.om.NodeName;
16
using JNamespaceMap = net.sf.saxon.om.NamespaceMap;
17
using JItem = net.sf.saxon.om.Item;
18
using JNodeInfo = net.sf.saxon.om.NodeInfo;
19
using JDotNetDomBuilder = net.sf.saxon.dotnet.DotNetDomBuilder;
20
using JDotNetOutputStream = net.sf.saxon.dotnet.DotNetOutputStream;
21
using JDotNetWriter = net.sf.saxon.dotnet.DotNetWriter;
22
using JDotNetReceiver = net.sf.saxon.dotnet.DotNetReceiver;
23
using JSerializationProperties = net.sf.saxon.serialize.SerializationProperties;
24
using JDestination = net.sf.saxon.s9api.Destination;
25
using JAbstractDestination = net.sf.saxon.s9api.AbstractDestination;
26
using JAction = net.sf.saxon.s9api.Action;
27
using java.net;
28
using net.sf.saxon.s9api;
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
		/// <param name="params1"></param>
849
        
850
		public JReceiver GetReceiver(JPipelineConfiguration pipe, JSerializationProperties params1)
851
        {
852
            JDotNetReceiver dnr = new JDotNetReceiver(writer);
853
			dnr.setPipelineConfiguration (pipe);
854
            dnr.setCloseAfterUse(closeAfterUse);
855
            return params1.makeSequenceNormalizer(dnr);
856
        }
857

    
858
        /// <summary>
859
		/// Return a <c>Receiver</c>. Saxon calls this method to obtain a Java <c>Receiver</c>, to which it then sends
860
        /// a sequence of events representing the content of an XML document. The method is intended
861
        /// primarily for internal use, and may give poor diagnostics if used incorrectly.
862
        /// </summary>
863
        /// <returns>The receiver</returns>
864
		/// <param name="pipe">The Saxon configuration as a <c>JPipelineConfiguration</c>. 
865
		/// This is supplied so that the destination can
866
        /// use information from the configuration (for example, a reference to the name pool)
867
		/// to construct or configure the returned <c>Receiver</c>.</param>
868
		/// <param name="value2">Serialization parameters known to the caller of the method; typically, output
869
        ///  properties defined in a stylesheet or query. These will mainly be of interest if the destination is performing serialization, but
870
        ///  soem properties (such as <c>item-separator</c>) are also used in other situations.</param>
871
        public override JReceiver getReceiver(JPipelineConfiguration pipe, JSerializationProperties value2)
872
        {
873
            return GetReceiver(pipe, value2); 
874
        }
875

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

    
896

    
897
    internal class AbstractDestination : XmlDestination
898
    {
899
        private Xslt30Transformer xslt30Transformer;
900
        private XmlDestination destination;
901

    
902
        internal AbstractDestination(Xslt30Transformer xslt30Transformer, XmlDestination destination)
903
        {
904
            this.xslt30Transformer = xslt30Transformer;
905
            this.destination = destination;
906
        }
907

    
908
        JDestination XmlDestination.GetUnderlyingDestination()
909
        {
910
            return xslt30Transformer.GetUnderlyingXslt30Transformer.asDocumentDestination(destination.GetUnderlyingDestination());
911
        }
912
    }
913

    
914

    
915
    /// <summary>
916
    /// An <c>XdmDestination</c> is an <c>XmlDestination</c> in which an <c>XdmNode</c> 
917
    /// is constructed to hold the output of a query or transformation: 
918
    /// that is, a tree using Saxon's implementation of the XDM data model.
919
    /// </summary>
920
    /// <remarks>
921
    /// <para>No data needs to be supplied to the <c>XdmDestination</c> object. The query or transformation
922
    /// populates an <c>XmlNode</c>, which may then be retrieved as the value of the <c>XmlNode</c>
923
    /// property.</para>
924
    /// <para>An <c>XdmDestination</c> can be reused to hold the results of a second transformation only
925
    /// if the <c>Reset</c> method is first called to reset its state.</para>
926
    /// </remarks>
927

    
928
    public class XdmDestination : XmlDestination
929
    {
930
        internal net.sf.saxon.s9api.XdmDestination destination;
931

    
932
        /// <summary>Construct an <c>XdmDestination</c></summary>
933

    
934
        public XdmDestination()
935
        {
936
            destination = new net.sf.saxon.s9api.XdmDestination();
937
        }
938

    
939
        ///<summary>
940
        /// The Tree Model implementation to be used for the constructed document. By default
941
		/// the <c>TinyTree</c> is used. The main reason for using the <c>LinkedTree</c> alternative is if
942
		/// updating is required (the <c>TinyTree</c> is not updateable).
943
        ///</summary>
944

    
945
        public TreeModel TreeModel
946
        {
947
            get
948
            {
949
                return  (TreeModel)destination.getTreeModel().getSymbolicValue();
950
            }
951
            set
952
            {
953
                destination.setTreeModel(net.sf.saxon.om.TreeModel.getTreeModel((int)value));
954
            }
955
        }
956

    
957
		/// <summary>This property determines the base URI of the constructed <c>XdmNode</c>. 
958
		/// If the <c>BaseUri</c> property of the <c>XdmDestination</c> is set before the destination is written to,
959
		/// then the constructed <c>XdmNode</c> will have this base URI. Setting this property after constructing the node
960
        /// has no effect.
961
        /// </summary>
962

    
963
        public Uri BaseUri
964
        {
965
            get { return new Uri(destination.getBaseURI().toASCIIString()); }
966
            set { destination.setBaseURI(new java.net.URI(value.ToString())); }
967
        }
968

    
969

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

    
973
        public void Reset()
974
        {
975
            destination.reset();
976
        }
977

    
978
        /// <summary>After construction, retrieve the constructed document node.</summary>
979
        /// <remarks>
980
        /// <para>The value of the property will be null if no data has been written to the
981
		/// <c>XdmDestination</c>, either because the process that writes to the destination has not
982
        /// yet been run, or because the process produced no output.</para>
983
        /// </remarks>
984

    
985
        public XdmNode XdmNode
986
        {
987
            get
988
            {
989
                JNodeInfo jnode = destination.getXdmNode().getUnderlyingNode();
990
                return (jnode == null ? null : (XdmNode)XdmValue.Wrap(jnode));
991
            }
992
        }
993

    
994

    
995
        /// <summary>
996
		/// Get the underlying Saxon <c>Destination</c> object from the <c>XdmDestination</c>.
997
        /// This method is for internal use but is provided for the benefit of applications that need to mix
998
        /// use of the Saxon .NET API with direct use of the underlying objects
999
        /// and methods offered by the Java implementation.
1000
        /// </summary>
1001
        public JDestination GetUnderlyingDestination()
1002
        {
1003
            return destination;
1004
        }
1005

    
1006

    
1007
        /// <summary>
1008
        /// Set the base URI of the resource being written to this destination
1009
        /// </summary>
1010
        /// <param name="uri">the base URI to be used</param>
1011
        public void setDestinationBaseURI(java.net.URI uri)
1012
        {
1013
            destination.setDestinationBaseURI(uri);
1014
        }
1015

    
1016
        /// <summary>
1017
        /// Get the base URI of the resource being written to this destination
1018
        /// </summary>
1019
        /// <returns>the base URI, or null if none is known</returns>
1020
        public java.net.URI getDestinationBaseURI()
1021
        {
1022
            return destination.getDestinationBaseURI();
1023
        }
1024

    
1025

    
1026

    
1027
        /// <summary>
1028
        /// Close the destination, allowing resources to be released. Saxon calls this
1029
        /// method when it has finished writing to the destination.
1030
        /// </summary>
1031
        public void Close()
1032
        {
1033
            destination.close();
1034
        }
1035

    
1036
        /// <summary>
1037
        /// <c>TreeProtector</c> is a filter that ensures that the events reaching the <c>Builder</c> constitute a single
1038
        /// tree rooted at an element or document node (because anything else will crash the builder)
1039
        /// </summary>
1040

    
1041
        public class TreeProtector : JProxyReceiver
1042
        {
1043

    
1044
            private int level = 0;
1045
            private bool ended = false;
1046

    
1047
            /// <summary>
1048
            /// Constructor
1049
            /// </summary>
1050
            /// <param name="next">Set the underlying receiver</param>
1051
            public TreeProtector(JReceiver next)
1052
                : base(next)
1053
            {
1054

    
1055
            }
1056

    
1057
            /// <summary>
1058
            /// Start of a document node
1059
            /// </summary>
1060
            /// <param name="properties"></param>
1061
            public override void startDocument(int properties)
1062
            {
1063
                if (ended)
1064
                {
1065
                    JXPathException e = new JXPathException("Only a single document can be written to an XdmDestination");
1066
                    throw new DynamicError(e);
1067
                }
1068
                base.startDocument(properties);
1069
                level++;
1070
            }
1071

    
1072
            /// <summary>
1073
            /// Notify the end of a document node
1074
            /// </summary>
1075
            public override void endDocument()
1076
            {
1077
                base.endDocument();
1078
                level--;
1079
                if (level == 0)
1080
                {
1081
                    ended = true;
1082
                }
1083
            }
1084

    
1085
            /// <summary>
1086
            /// Notify the start of an element
1087
            /// </summary>
1088
            /// <param name="nameCode"></param>
1089
			/// <param name="typeCode"></param>
1090
			/// <param name="attributes"></param>
1091
			/// <param name="namespaces"></param>
1092
            /// <param name="location"></param>
1093
            /// <param name="properties"></param>
1094
            public override void startElement(JNodeName nameCode, JSchemaType typeCode, JAttributeMap attributes, JNamespaceMap namespaces, JLocation location, int properties)
1095
            {
1096
                if (ended)
1097
                {
1098
                    JXPathException e = new JXPathException("Only a single root node can be written to an XdmDestination");
1099
                    throw new DynamicError(e);
1100
                }
1101
                base.startElement(nameCode, typeCode, attributes, namespaces, location, properties);
1102
                level++;
1103
            }
1104

    
1105
            /// <summary>
1106
            /// End of element
1107
            /// </summary>
1108
            public override void endElement()
1109
            {
1110
                base.endElement();
1111
                level--;
1112
                if (level == 0)
1113
                {
1114
                    ended = true;
1115
                }
1116
            }
1117

    
1118
            /// <summary>
1119
            /// Character data
1120
            /// </summary>
1121
            /// <param name="chars">Character data as input</param>
1122
            /// <param name="location">Provides information such as line number and system ID</param>
1123
            /// <param name="properties">Bit significant value. The following bits are defined</param>
1124
			public override void characters(JCharSequence chars, JLocation location, int properties)
1125
            {
1126
                if (level == 0)
1127
                {
1128
                    JXPathException e = new JXPathException("When writing to an XdmDestination, text nodes are only allowed within a document or element node");
1129
                    throw new DynamicError(e);
1130
                }
1131
                base.characters(chars, location, properties);
1132
            }
1133

    
1134
            /// <summary>
1135
            /// Processing instruction
1136
            /// </summary>
1137
            /// <param name="target">The PI name. This must be a legal name (it will not be checked)</param>
1138
            /// <param name="data">The data portion of the processing instruction</param>
1139
            /// <param name="location">provides information about the PI</param>
1140
            /// <param name="properties">Additional information about the PI</param>
1141
			public override void processingInstruction(String target, JCharSequence data, JLocation location, int properties)
1142
            {
1143
                if (level == 0)
1144
                {
1145
                    JXPathException e = new JXPathException("When writing to an XdmDestination, processing instructions are only allowed within a document or element node");
1146
                    throw new DynamicError(e);
1147
                }
1148
                base.processingInstruction(target, data, location, properties);
1149
            }
1150

    
1151
            /// <summary>
1152
            /// Output a comment
1153
            /// </summary>
1154
            /// <param name="chars">The content of the comment</param>
1155
            /// <param name="location">provides information such as line number and system ID</param>
1156
            /// <param name="properties">Additional information about the comment</param>
1157
			public override void comment(JCharSequence chars, JLocation location, int properties)
1158
            {
1159
                if (level == 0)
1160
                {
1161
                    JXPathException e = new JXPathException("When writing to an XdmDestination, comment nodes are only allowed within a document or element node");
1162
                }
1163
                base.comment(chars, location, properties);
1164
            }
1165

    
1166

    
1167
            /// <summary>
1168
            /// Append an  arbitrary item (node or atomic value) to the output
1169
            /// </summary>
1170
            /// <param name="item">the item to be appended</param>
1171
            /// <param name="location">the location of the calling instruction, for diagnostics</param>
1172
            /// <param name="copyNamespaces">if the item is an element node, this indicates whether its namespace need to be copied. 
1173
            /// 0x80000 means ALL_NAMESPACE, 0x40000 means LOCAL_NAMESPACE and 0 means no namespace</param>
1174
			public override void append(JItem item, JLocation location, int copyNamespaces)
1175
            {
1176
                if (level == 0)
1177
                {
1178
                    JXPathException e = new JXPathException("When writing to an XdmDestination, atomic values are only allowed within a document or element node");
1179
                }
1180
                base.append(item, location, copyNamespaces);
1181
            }
1182

    
1183
        }
1184
    }
1185

    
1186

    
1187
}
1188

    
1189
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1190
// Copyright (c) 2020 Saxonica Limited.
1191
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
1192
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
1193
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
1194
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
(2-2/11)