Project

Profile

Help

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

he / latest9.9 / samples / cs / ExamplesPE.cs @ 063bf4dc

1
using System;
2
using System.IO;
3
using System.Collections;
4
using System.Xml;
5
using System.Net;
6
using Saxon.Api;
7
using System.Collections.Generic;
8

    
9
namespace SaxonPE
10
{
11
    class ExamplesPE
12
    {
13
        /// <summary>
14
        /// Run Saxon XSLT and XQuery sample applications in Saxon Professional Edition on .NET
15
        /// </summary>
16
        /// <param name="argv">
17
        /// <para>Options:</para>
18
        /// <list>
19
        /// <item>-test:testname  run a specific test</item>
20
        /// <item>-dir:samplesdir directory containing the sample data files (default %SAXON_HOME%/samples)</item>
21
        /// <item>-ask:yes|no     indicates whether to prompt for confirmation after each test (default yes)</item>
22
        /// </list>
23
        /// </param>
24

    
25

    
26
        public static void Main(String[] argv)
27
        {
28

    
29
            Example[] examples = {
30
                new XPathSimple(),
31
                new XPathSimple2(),
32
                new XPathVariables(),
33
                new XPathUndeclaredVariables(),
34
                new XPathWithStaticError(),
35
                new XPathWithDynamicError(),
36
                new XsltSimple1(),
37
                new XsltSimple2(),
38
                new XsltSimple3(),
39
                new XsltStripSpace(),
40
                new XsltReuseExecutable(),
41
                new XsltReuseTransformer(),
42
                new XsltFilterChain(),
43
                new XsltDomToDom(),
44
                new XsltXdmToXdm(),
45
                new XsltXdmElementToXdm(),
46
                new XsltUsingSourceResolver(),
47
                new XsltSettingOutputProperties(),
48
                new XsltDisplayingErrors(),
49
                new XsltCapturingErrors(),
50
                new XsltCapturingMessages(),
51
                new XsltProcessingInstruction(),
52
                new XsltShowingLineNumbers(),
53
                new XsltMultipleOutput(),
54
                new XsltUsingResultHandler(),
55
                new XsltUsingIdFunction(),
56
                new XsltUsingRegisteredCollection(),
57
                new XsltUsingDirectoryCollection(),
58
                new XsltExtensibility(),
59
                new XsltIntegratedExtension(),
60
                new XsltSimpleExtension(),
61
                new XQueryToStream(),
62
                new XQueryToAtomicValue(),
63
                new XQueryToSequence(),
64
                new XQueryToDom(),
65
                new XQueryToXdm(),
66
                new XQueryCallFunction(),
67
                new XQueryFromXmlReader(),
68
                new XQueryToSerializedSequence(),
69
                new XQueryUsingParameter(),
70
                new XQueryMultiModule(),
71
                new XQueryTryCatch(),
72
                new XQueryExtensibility()
73
            };
74

    
75
            Boolean ask = true;
76
            String test = "all";
77

    
78
            String samplesPath = null;
79
            Uri samplesDir;
80

    
81
            foreach (String s in argv)
82
            {
83
                if (s.StartsWith("-test:"))
84
                {
85
                    test = s.Substring(6);
86
                }
87
                else if (s.StartsWith("-dir:"))
88
                {
89
                    samplesPath = s.Substring(5);
90
                }
91
                else if (s == "-ask:yes")
92
                {
93
                    // no action
94
                }
95
                else if (s == "-ask:no")
96
                {
97
                    ask = false;
98
                }
99
                else if (s == "-?")
100
                {
101
                    Console.WriteLine("ExamplesPE -dir:samples -test:testname -ask:yes|no");
102
                }
103
                else
104
                {
105
                    Console.WriteLine("Unrecognized Argument: " + s);
106
                    return;
107
                }
108
            }
109
            if (samplesPath != null)
110
            {
111
                if (samplesPath.StartsWith("file:///"))
112
                {
113
                    samplesPath = samplesPath.Substring(8);
114
                }
115
                else if (samplesPath.StartsWith("file:/"))
116
                {
117
                    samplesPath = samplesPath.Substring(6);
118
                }
119

    
120
            }
121
            else
122
            {
123
                String home = Environment.GetEnvironmentVariable("SAXON_HOME");
124
                if (home == null)
125
                {
126
                    Console.WriteLine("No input directory supplied, and SAXON_HOME is not set");
127
                    return;
128
                }
129
                else
130
                {
131
                    if (!(home.EndsWith("/") || home.EndsWith("\\")))
132
                    {
133
                        home = home + "/";
134
                    }
135
                    samplesPath = home + "samples/";
136
                }
137
            }
138

    
139
            if (!(samplesPath.EndsWith("/") || samplesPath.EndsWith("\\")))
140
            {
141
                samplesPath = samplesPath + "/";
142
            }
143

    
144
            if (!File.Exists(samplesPath + "data/books.xml"))
145
            {
146
                Console.WriteLine("Supplied samples directory " + samplesPath + " does not contain the Saxon sample data files");
147
                return;
148
            }
149

    
150
            try
151
            {
152
                samplesDir = new Uri(samplesPath);
153
            }
154
            catch
155
            {
156
                Console.WriteLine("Invalid URI for samples directory: " + samplesPath);
157
                return;
158
            }
159

    
160
            Boolean found = false;
161
            foreach (Example ex in examples)
162
            {
163
                if (test == "all" || test == ex.testName)
164
                {
165
                    Console.WriteLine("\n\n===== " + ex.testName + " =======\n");
166
                    found = true;
167
                    try
168
                    {
169
                        ex.run(samplesDir);
170
                    }
171
                    catch (Saxon.Api.StaticError se)
172
                    {
173
                        Console.WriteLine("Test failed with static error " + (se.ErrorCode != null ? se.ErrorCode.LocalName : "") + ": " + se.Message);
174
                    }
175
                    catch (Saxon.Api.DynamicError de)
176
                    {
177
                        Console.WriteLine("Test failed with dynamic error " + (de.ErrorCode != null ? de.ErrorCode.LocalName : "") + ": " + de.Message);
178
                    }
179
                    catch (Exception exc)
180
                    {
181
                        Console.WriteLine("Test failed unexpectedly (" + exc.GetType() + "): " + exc.Message);
182
                        Console.WriteLine(exc.StackTrace);
183
                    }
184
                    if (ask)
185
                    {
186
                        Console.WriteLine("\n\nContinue? - type (Y(es)/N(o)/A(ll))");
187
                        String answer = Console.ReadLine();
188
                        if (answer == "N" || answer == "n")
189
                        {
190
                            break;
191
                        }
192
                        else if (answer == "A" || answer == "a")
193
                        {
194
                            ask = false;
195
                        }
196
                    }
197
                }
198
            }
199
            if (!found)
200
            {
201
                Console.WriteLine("Please supply a valid test name, or 'all' ('" + test + "' is invalid)");
202
            }
203
            Console.WriteLine("\n==== done! ====");
204
        }
205
    }
206

    
207
    ///<summary>
208
    /// Each of the example programs is implemented as a subclass of the abstract class Example
209
    ///</summary> 
210

    
211

    
212
    public abstract class Example
213
    {
214
        /// <summary>
215
        /// Read-only property: the name of the test example
216
        /// </summary>
217
        public abstract String testName { get; }
218
        /// <summary>
219
        /// Entry point for running the example
220
        /// </summary>
221
        public abstract void run(Uri samplesDir);
222
    }
223

    
224
    /// <summary>
225
    /// Evaluate an XPath expression selecting from a source document supplied as a URI
226
    /// </summary>
227

    
228
    public class XPathSimple : Example
229
    {
230

    
231
        public override String testName
232
        {
233
            get { return "XPathSimple"; }
234
        }
235

    
236
        public override void run(Uri samplesDir)
237
        {
238
            // Create a Processor instance.
239
            Processor processor = new Processor();
240

    
241
            // Load the source document
242
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/books.xml"));
243

    
244
            // Create an XPath compiler
245
            XPathCompiler xpath = processor.NewXPathCompiler();
246

    
247
            // Enable caching, so each expression is only compiled once
248
            xpath.Caching = true;
249

    
250
            // Compile and evaluate some XPath expressions
251
            foreach (XdmItem item in xpath.Evaluate("//ITEM", input))
252
            {
253
                Console.WriteLine("TITLE: " + xpath.EvaluateSingle("string(TITLE)", item));
254
                Console.WriteLine("PRICE: " + xpath.EvaluateSingle("string(PRICE)", item));
255
            }
256
        }
257
    }
258

    
259
    /// <summary>
260
    /// Evaluate an XPath expression against a source document, returning its effective boolean value
261
    /// </summary>
262

    
263
    public class XPathSimple2 : Example
264
    {
265

    
266
        public override String testName
267
        {
268
            get { return "XPathSimple2"; }
269
        }
270

    
271
        public override void run(Uri samplesDir)
272
        {
273
            // Create a Processor instance.
274
            Processor processor = new Processor();
275

    
276
            // Load the source document
277
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/books.xml"));
278

    
279
            // Create an XPath compiler
280
            XPathCompiler xpath = processor.NewXPathCompiler();
281

    
282
            // Enable caching, so each expression is only compiled once
283
            xpath.Caching = true;
284

    
285
            // Compile and evaluate an XPath expression
286
            XPathSelector selector = xpath.Compile("//ITEM").Load();
287
            selector.ContextItem = input;
288
            Console.WriteLine(selector.EffectiveBooleanValue());
289

    
290
        }
291
    }
292

    
293
    /// <summary>
294
    /// Evaluate an XPath expression using variables (and no source document)
295
    /// </summary>
296

    
297
    public class XPathVariables : Example
298
    {
299

    
300
        public override String testName
301
        {
302
            get { return "XPathVariables"; }
303
        }
304

    
305
        public override void run(Uri samplesDir)
306
        {
307
            // Create a Processor instance.
308
            Processor processor = new Processor();
309

    
310
            // Create the XPath expression.
311
            XPathCompiler compiler = processor.NewXPathCompiler();
312
            compiler.DeclareVariable(new QName("", "a"));
313
            compiler.DeclareVariable(new QName("", "b"));
314
            XPathSelector selector = compiler.Compile("$a + $b").Load();
315

    
316
            // Set the values of the variables
317
            selector.SetVariable(new QName("", "a"), new XdmAtomicValue(2));
318
            selector.SetVariable(new QName("", "b"), new XdmAtomicValue(3));
319

    
320
            // Evaluate the XPath expression
321
            Console.WriteLine(selector.EvaluateSingle().ToString());
322
        }
323
    }
324

    
325
    /// <summary>
326
    /// Evaluate an XPath expression using variables without explicit declaration
327
    /// </summary>
328

    
329
    public class XPathUndeclaredVariables : Example
330
    {
331

    
332
        public override String testName
333
        {
334
            get { return "XPathUndeclaredVariables"; }
335
        }
336

    
337
        public override void run(Uri samplesDir)
338
        {
339
            // Create a Processor instance.
340
            Processor processor = new Processor();
341

    
342
            // Create the XPath expression.
343
            XPathCompiler compiler = processor.NewXPathCompiler();
344
            compiler.AllowUndeclaredVariables = true;
345
            XPathExecutable expression = compiler.Compile("$a + $b");
346
            XPathSelector selector = expression.Load();
347

    
348
            // Set the values of the variables
349
            IEnumerator<QName> vars = expression.EnumerateExternalVariables2();
350
            while (vars.MoveNext())
351
            {
352
                selector.SetVariable((QName)vars.Current, new XdmAtomicValue(10));
353
            }
354

    
355
            // Evaluate the XPath expression
356
            Console.WriteLine(selector.EvaluateSingle().ToString());
357
        }
358
    }
359

    
360
    /// <summary>
361
    /// Evaluate an XPath expression throwing a static error
362
    /// </summary>
363

    
364
    public class XPathWithStaticError : Example
365
    {
366

    
367
        public override String testName
368
        {
369
            get { return "XPathWithStaticError"; }
370
        }
371

    
372
        public override void run(Uri samplesDir)
373
        {
374
            // Create a Processor instance.
375
            Processor processor = new Processor();
376

    
377
            // Create the XPath expression.
378
            XPathCompiler compiler = processor.NewXPathCompiler();
379
            compiler.AllowUndeclaredVariables = true;
380
            XPathExecutable expression = compiler.Compile("1 + unknown()");
381
            XPathSelector selector = expression.Load();
382

    
383
            // Evaluate the XPath expression
384
            Console.WriteLine(selector.EvaluateSingle().ToString());
385
        }
386
    }
387

    
388
    /// <summary>
389
    /// Evaluate an XPath expression throwing a dynamic error
390
    /// </summary>
391

    
392
    public class XPathWithDynamicError : Example
393
    {
394

    
395
        public override String testName
396
        {
397
            get { return "XPathWithDynamicError"; }
398
        }
399

    
400
        public override void run(Uri samplesDir)
401
        {
402
            // Create a Processor instance.
403
            Processor processor = new Processor();
404

    
405
            // Create the XPath expression.
406
            XPathCompiler compiler = processor.NewXPathCompiler();
407
            compiler.AllowUndeclaredVariables = true;
408
            XPathExecutable expression = compiler.Compile("$a gt $b");
409
            XPathSelector selector = expression.Load();
410

    
411
            // Set the values of the variables
412
            selector.SetVariable(new QName("", "a"), new XdmAtomicValue(10));
413
            selector.SetVariable(new QName("", "b"), new XdmAtomicValue("Paris"));
414

    
415
            // Evaluate the XPath expression
416
            Console.WriteLine(selector.EvaluateSingle().ToString());
417
        }
418
    }
419

    
420
    /// <summary>
421
    /// XSLT 2.0 transformation with source document and stylesheet supplied as URIs
422
    /// </summary>
423

    
424
    public class XsltSimple1 : Example
425
    {
426

    
427
        public override String testName
428
        {
429
            get { return "XsltSimple1"; }
430
        }
431

    
432
        public override void run(Uri samplesDir)
433
        {
434
            // Create a Processor instance.
435
            Processor processor = new Processor();
436

    
437
            // Load the source document
438
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/books.xml"));
439

    
440
            // Create a transformer for the stylesheet.
441
            Xslt30Transformer transformer = processor.NewXsltCompiler().Compile(new Uri(samplesDir, "styles/books.xsl")).Load30();
442

    
443
            // Set the root node of the source document to be the global context item
444
            transformer.GlobalContextItem = input;
445

    
446
            // Create a serializer, with output to the standard output stream
447
            Serializer serializer = processor.NewSerializer();
448
            serializer.SetOutputWriter(Console.Out);
449

    
450
            // Transform the source XML and serialize the result document
451
            transformer.ApplyTemplates(input, serializer);
452
        }
453
    }
454

    
455
    /// <summary>
456
    /// Run a transformation, sending the serialized output to a file
457
    /// </summary>
458

    
459
    public class XsltSimple2 : Example
460
    {
461

    
462
        public override String testName
463
        {
464
            get { return "XsltSimple2"; }
465
        }
466

    
467
        public override void run(Uri samplesDir)
468
        {
469
            // Create a Processor instance.
470
            Processor processor = new Processor();
471

    
472
            // Load the source document
473
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/books.xml"));
474

    
475
            // Create a transformer for the stylesheet.
476
            Xslt30Transformer transformer = processor.NewXsltCompiler().Compile(new Uri(samplesDir, "styles/identity.xsl")).Load30();
477

    
478
            // Create a serializer
479
            String outfile = "OutputFromXsltSimple2.xml";
480
            Serializer serializer = processor.NewSerializer();
481
            serializer.SetOutputStream(new FileStream(outfile, FileMode.Create, FileAccess.Write));
482

    
483
            // Transform the source XML and serialize the result to the output file.
484
            transformer.ApplyTemplates(input, serializer);
485

    
486
            Console.WriteLine("\nOutput written to " + outfile + "\n");
487
        }
488
    }
489

    
490
    /// <summary>
491
    /// XSLT 2.0 transformation with source document and stylesheet supplied as files
492
    /// </summary>
493

    
494
    public class XsltSimple3 : Example
495
    {
496

    
497
        public override String testName
498
        {
499
            get { return "XsltSimple3"; }
500
        }
501

    
502
        public override void run(Uri samplesDir)
503
        {
504
            if (samplesDir.Scheme != Uri.UriSchemeFile)
505
            {
506
                Console.WriteLine("Supplied URI must be a file directory");
507
            }
508
            String dir = samplesDir.AbsolutePath;
509
            String sourceFile = dir + "data/books.xml";
510
            String styleFile = dir + "styles/books.xsl";
511

    
512
            // Create a Processor instance.
513
            Processor processor = new Processor();
514

    
515
            // Load the source document
516
            DocumentBuilder builder = processor.NewDocumentBuilder();
517
            builder.BaseUri = new Uri(samplesDir, "data/books.xml");
518

    
519
            XdmNode input = builder.Build(File.OpenRead(sourceFile));
520

    
521
            // Create a transformer for the stylesheet.
522
            XsltCompiler compiler = processor.NewXsltCompiler();
523
            compiler.BaseUri = new Uri(samplesDir, "styles/books.xsl");
524
            Xslt30Transformer transformer = compiler.Compile(File.OpenRead(styleFile)).Load30();
525

    
526
            // Set the root node of the source document to be the global context item
527
            transformer.GlobalContextItem = input;
528

    
529
            // Create a serializer, with output to the standard output stream
530
            Serializer serializer = processor.NewSerializer();
531
            serializer.SetOutputWriter(Console.Out);
532

    
533
            // Transform the source XML and serialize the result document
534
            transformer.ApplyTemplates(input, serializer);
535
        }
536
    }
537

    
538

    
539
    /// <summary>
540
    /// XSLT 2.0 transformation showing stripping of whitespace controlled by the stylesheet
541
    /// </summary>
542

    
543
    public class XsltStripSpace : Example
544
    {
545

    
546
        public override String testName
547
        {
548
            get { return "XsltStripSpace"; }
549
        }
550

    
551
        public override void run(Uri samplesDir)
552
        {
553
            Processor processor = new Processor();
554

    
555
            // Load the source document
556
            DocumentBuilder builder = processor.NewDocumentBuilder();
557
            builder.BaseUri = samplesDir;
558

    
559
            String doc = "<doc>  <a>  <b>text</b>  </a>  <a/>  </doc>";
560
            MemoryStream ms = new MemoryStream();
561
            StreamWriter tw = new StreamWriter(ms);
562
            tw.Write(doc);
563
            tw.Flush();
564
            Stream instr = new MemoryStream(ms.GetBuffer(), 0, (int)ms.Length);
565
            XdmNode input = builder.Build(instr);
566

    
567
            // Create a transformer for the stylesheet.
568
            String stylesheet =
569
                "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='2.0'>" +
570
                "<xsl:strip-space elements='*'/>" +
571
                "<xsl:template match='/'>" +
572
                "  <xsl:copy-of select='.'/>" +
573
                "</xsl:template>" +
574
                "</xsl:stylesheet>";
575

    
576
            XsltCompiler compiler = processor.NewXsltCompiler();
577
            compiler.BaseUri = samplesDir;
578
            Xslt30Transformer transformer = compiler.Compile(new XmlTextReader(new StringReader(stylesheet))).Load30();
579

    
580
            // Create a serializer, with output to the standard output stream
581
            Serializer serializer = processor.NewSerializer();
582
            serializer.SetOutputWriter(Console.Out);
583

    
584
            // Transform the source XML and serialize the result document
585
            transformer.ApplyTemplates(input, serializer);
586
        }
587
    }
588

    
589

    
590
    /// <summary>
591
    /// Run a transformation, compiling the stylesheet once (into an XsltExecutable) and using it to transform two 
592
    /// different source documents
593
    /// </summary>
594

    
595
    public class XsltReuseExecutable : Example
596
    {
597

    
598
        public override String testName
599
        {
600
            get { return "XsltReuseExecutable"; }
601
        }
602

    
603
        public override void run(Uri samplesDir)
604
        {
605
            // Create a Processor instance.
606
            Processor processor = new Processor();
607

    
608
            // Create a compiled stylesheet
609
            XsltExecutable templates = processor.NewXsltCompiler().Compile(new Uri(samplesDir, "styles/summarize.xsl"));
610

    
611
            // Note: we could actually use the same Xslt30Transformer in this case.
612
            // But in principle, the two transformations could be done in parallel in separate threads.
613

    
614
            String sourceFile1 = "data/books.xml";
615
            String sourceFile2 = "data/othello.xml";
616

    
617
            // Do the first transformation
618
            Console.WriteLine("\n\n----- transform of " + sourceFile1 + " -----");
619
            Xslt30Transformer transformer1 = templates.Load30();
620
            XdmNode input1 = processor.NewDocumentBuilder().Build(new Uri(samplesDir, sourceFile1));
621
            transformer1.ApplyTemplates(input1, processor.NewSerializer(Console.Out));     // default destination is Console.Out
622

    
623
            // Do the second transformation
624
            Console.WriteLine("\n\n----- transform of " + sourceFile2 + " -----");
625
            Xslt30Transformer transformer2 = templates.Load30();
626
            XdmNode input2 = processor.NewDocumentBuilder().Build(new Uri(samplesDir, sourceFile2));
627
            transformer2.ApplyTemplates(input2, processor.NewSerializer(Console.Out));     // default destination is Console.Out
628
        }
629
    }
630

    
631
    /// <summary>
632
    /// Show that the Xslt30Transformer is serially reusable; run a transformation twice using the same stylesheet
633
    /// and the same stylesheet parameters, but with a different input document.
634
    /// </summary>
635

    
636
    public class XsltReuseTransformer : Example
637
    {
638

    
639
        public override String testName
640
        {
641
            get { return "XsltReuseTransformer"; }
642
        }
643

    
644
        public override void run(Uri samplesDir)
645
        {
646
            // Create a Processor instance.
647
            Processor processor = new Processor();
648

    
649
            // Compile the stylesheet
650
            XsltExecutable exec = processor.NewXsltCompiler().Compile(new Uri(samplesDir, "styles/summarize.xsl"));
651

    
652
            // Create a transformer 
653
            Xslt30Transformer transformer = exec.Load30();
654

    
655
            // Set the stylesheet parameters
656
            Dictionary<QName, XdmValue> params1 = new Dictionary<QName, XdmValue>();
657
            params1.Add(new QName("", "", "include-attributes"), new XdmAtomicValue(false));
658
            transformer.SetStylesheetParameters(params1);
659

    
660
            // Load the 1st source document, building a tree
661
            XdmNode input1 = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/books.xml"));
662

    
663
            // Run the transformer once
664
            XdmDestination results = new XdmDestination();
665
            transformer.ApplyTemplates(input1, results);
666
            Console.WriteLine("1: " + results.XdmNode.OuterXml);
667

    
668
            // Load the 2nd source document, building a tree
669
            XdmNode input2 = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/more-books.xml"));
670

    
671
            // Run the transformer again
672
            results.Reset();
673
            transformer.ApplyTemplates(input2, results);
674
            Console.WriteLine("2: " + results.XdmNode.OuterXml);
675
        }
676
    }
677

    
678
    /// <summary>
679
    /// Run a sequence of transformations in a pipeline, each one acting as a filter
680
    /// </summary>
681

    
682
    public class XsltFilterChain : Example
683
    {
684

    
685
        public override String testName
686
        {
687
            get { return "XsltFilterChain"; }
688
        }
689

    
690
        public override void run(Uri samplesDir)
691
        {
692
            // Create a Processor instance.
693
            Processor processor = new Processor();
694

    
695
            // Load the source document
696
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/books.xml"));
697

    
698
            // Create a compiler
699
            XsltCompiler compiler = processor.NewXsltCompiler();
700

    
701
            // Compile all three stylesheets
702
            Xslt30Transformer transformer1 = compiler.Compile(new Uri(samplesDir, "styles/identity.xsl")).Load30();
703
            Xslt30Transformer transformer2 = compiler.Compile(new Uri(samplesDir, "styles/books.xsl")).Load30();
704
            Xslt30Transformer transformer3 = compiler.Compile(new Uri(samplesDir, "styles/summarize.xsl")).Load30();
705

    
706
            // Now run them in series
707
            XdmDestination results1 = new XdmDestination();
708
            transformer1.ApplyTemplates(input, results1);
709
            //Console.WriteLine("After phase 1:");
710
            //Console.WriteLine(results1.XdmNode.OuterXml);
711

    
712
            XdmDestination results2 = new XdmDestination();
713
            transformer2.GlobalContextItem = results1.XdmNode;
714
            transformer2.ApplyTemplates(results1.XdmNode, results2);
715
            //Console.WriteLine("After phase 2:");
716
            //Console.WriteLine(results2.XdmNode.OuterXml);
717

    
718
            XdmDestination results3 = new XdmDestination();
719
            transformer3.ApplyTemplates(results2.XdmNode, results3);
720
            Console.WriteLine("After phase 3:");
721
            Console.WriteLine(results3.XdmNode.OuterXml);
722
        }
723
    }
724

    
725
    /// <summary>
726
    /// Transform from an XDM tree to an XDM tree
727
    /// </summary>
728

    
729
    public class XsltXdmToXdm : Example
730
    {
731

    
732
        public override String testName
733
        {
734
            get { return "XsltXdmToXdm"; }
735
        }
736

    
737
        public override void run(Uri samplesDir)
738
        {
739
            // Create a Processor instance.
740
            Processor processor = new Processor();
741

    
742
            // Load the source document
743
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/books.xml"));
744

    
745
            // Create a compiler
746
            XsltCompiler compiler = processor.NewXsltCompiler();
747

    
748
            // Compile the stylesheet
749
            Xslt30Transformer transformer = compiler.Compile(new Uri(samplesDir, "styles/summarize.xsl")).Load30();
750

    
751
            // Run the transformation
752
            XdmDestination result = new XdmDestination();
753
            transformer.ApplyTemplates(input, result);
754

    
755
            // Serialize the result so we can see that it worked
756
            StringWriter sw = new StringWriter();
757
            result.XdmNode.WriteTo(new XmlTextWriter(sw));
758
            Console.WriteLine(sw.ToString());
759

    
760
            // Note: we don't do 
761
            //   result.XdmNode.WriteTo(new XmlTextWriter(Console.Out));
762
            // because that results in the Console.out stream being closed, 
763
            // with subsequent attempts to write to it being rejected.
764
        }
765
    }
766

    
767
    /// <summary>
768
    /// Run an XSLT transformation from an XDM tree, starting at a node that is not the document node
769
    /// </summary>
770

    
771
    public class XsltXdmElementToXdm : Example
772
    {
773

    
774
        public override String testName
775
        {
776
            get { return "XsltXdmElementToXdm"; }
777
        }
778

    
779
        public override void run(Uri samplesDir)
780
        {
781
            // Create a Processor instance.
782
            Processor processor = new Processor();
783

    
784
            // Load the source document
785
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/othello.xml"));
786

    
787
            // Navigate to the first grandchild
788
            XPathSelector eval = processor.NewXPathCompiler().Compile("/PLAY/FM[1]").Load();
789
            eval.ContextItem = input;
790
            input = (XdmNode)eval.EvaluateSingle();
791

    
792
            // Create an XSLT compiler
793
            XsltCompiler compiler = processor.NewXsltCompiler();
794

    
795
            // Compile the stylesheet
796
            Xslt30Transformer transformer = compiler.Compile(new Uri(samplesDir, "styles/summarize.xsl")).Load30();
797

    
798
            // Run the transformation
799
            XdmDestination result = new XdmDestination();
800
            transformer.ApplyTemplates(input, result);
801

    
802
            // Serialize the result so we can see that it worked
803
            Console.WriteLine(result.XdmNode.OuterXml);
804
        }
805
    }
806

    
807
    /// <summary>
808
    /// Run a transformation from a DOM (System.Xml.Document) input to a DOM output
809
    /// </summary>
810

    
811
    public class XsltDomToDom : Example
812
    {
813

    
814
        public override String testName
815
        {
816
            get { return "XsltDomToDom"; }
817
        }
818

    
819
        public override void run(Uri samplesDir)
820
        {
821
            // Create a Processor instance.
822
            Processor processor = new Processor();
823

    
824
            // Load the source document (in practice, it would already exist as a DOM)
825
            XmlDocument doc = new XmlDocument();
826
            doc.Load(new XmlTextReader(samplesDir.AbsolutePath + "data/othello.xml"));
827
            XdmNode input = processor.NewDocumentBuilder().Wrap(doc);
828

    
829
            // Create a compiler
830
            XsltCompiler compiler = processor.NewXsltCompiler();
831

    
832
            // Compile the stylesheet
833
            Xslt30Transformer transformer = compiler.Compile(new Uri(samplesDir, "styles/summarize.xsl")).Load30();
834

    
835
            // Run the transformation
836
            DomDestination result = new DomDestination();
837
            transformer.ApplyTemplates(input, result);
838

    
839
            // Serialize the result so we can see that it worked
840
            Console.WriteLine(result.XmlDocument.OuterXml);
841
        }
842
    }
843

    
844

    
845
    /// <summary>
846
    /// Run a transformation driven by an xml-stylesheet processing instruction in the source document
847
    /// </summary>
848

    
849
    public class XsltProcessingInstruction : Example
850
    {
851

    
852
        public override string testName
853
        {
854
            get { return "XsltProcessingInstruction"; }
855
        }
856

    
857
        public override void run(Uri samplesDir)
858
        {
859
            // Create a Processor instance.
860
            Processor processor = new Processor();
861
            XsltExecutable exec;
862

    
863
            // Load the source document
864
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/books.xml"));
865
            //Console.WriteLine("=============== source document ===============");
866
            //Console.WriteLine(input.OuterXml);
867
            //Console.WriteLine("=========== end of source document ============");
868

    
869
            // Navigate to the xml-stylesheet processing instruction having the pseudo-attribute type=text/xsl;
870
            // then extract the value of the href pseudo-attribute if present
871

    
872
            String path = @"/processing-instruction(xml-stylesheet)[matches(.,'type\s*=\s*[''""]text/xsl[''""]')]" +
873
                    @"/replace(., '.*?href\s*=\s*[''""](.*?)[''""].*', '$1')";
874

    
875
            XPathSelector eval = processor.NewXPathCompiler().Compile(path).Load();
876
            eval.ContextItem = input;
877
            XdmAtomicValue hrefval = (XdmAtomicValue)eval.EvaluateSingle();
878
            String href = (hrefval == null ? null : hrefval.ToString());
879

    
880
            if (href == null || href == "")
881
            {
882
                Console.WriteLine("No suitable xml-stylesheet processing instruction found");
883
                return;
884

    
885
            }
886
            else if (href[0] == '#')
887
            {
888

    
889
                // The stylesheet is embedded in the source document and identified by a URI of the form "#id"
890

    
891
                Console.WriteLine("Locating embedded stylesheet with href = " + href);
892
                String idpath = "id('" + href.Substring(1) + "')";
893
                eval = processor.NewXPathCompiler().Compile(idpath).Load();
894
                eval.ContextItem = input;
895
                XdmNode node = (XdmNode)eval.EvaluateSingle();
896
                if (node == null)
897
                {
898
                    Console.WriteLine("No element found with ID " + href.Substring(1));
899
                    return;
900
                }
901
                exec = processor.NewXsltCompiler().Compile(node);
902

    
903
            }
904
            else
905
            {
906

    
907
                // The stylesheet is in an external document
908

    
909
                Console.WriteLine("Locating stylesheet at uri = " + new Uri(input.BaseUri, href));
910

    
911
                // Fetch and compile the referenced stylesheet
912
                exec = processor.NewXsltCompiler().Compile(new Uri(input.BaseUri, href.ToString()));
913
            }
914

    
915
            // Create a transformer 
916
            Xslt30Transformer transformer = exec.Load30();
917

    
918
            // Set the root node of the source document to be the global context item
919
            transformer.GlobalContextItem = input;
920

    
921
            // Run it       
922
            XdmDestination results = new XdmDestination();
923
            transformer.ApplyTemplates(input, results);
924
            Console.WriteLine(results.XdmNode.OuterXml);
925

    
926
        }
927
    }
928

    
929
    /// <summary>
930
    /// Run an XSLT transformation setting serialization properties from the calling application
931
    /// </summary>
932

    
933
    public class XsltSettingOutputProperties : Example
934
    {
935

    
936
        public override string testName
937
        {
938
            get { return "XsltSettingOutputProperties"; }
939
        }
940

    
941
        public override void run(Uri samplesDir)
942
        {
943
            // Create a Processor instance.
944
            Processor processor = new Processor();
945

    
946
            // Load the source document
947
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/books.xml"));
948

    
949
            // Create a transformer for the stylesheet.
950
            Xslt30Transformer transformer = processor.NewXsltCompiler().Compile(new Uri(samplesDir, "styles/summarize.xsl")).Load30();
951

    
952
            // Create a serializer, with output to the standard output stream
953
            Serializer serializer = processor.NewSerializer();
954
            serializer.SetOutputProperty(Serializer.METHOD, "xml");
955
            serializer.SetOutputProperty(Serializer.INDENT, "no");
956
            serializer.SetOutputWriter(Console.Out);
957

    
958
            // Transform the source XML and serialize the result document
959
            transformer.ApplyTemplates(input, serializer);
960
        }
961

    
962
    }
963

    
964
    /// <summary>
965
    /// Run an XSLT transformation making use of an XmlResolver to resolve URIs at document build time, at stylesheet compile time 
966
    /// and at transformation run-time
967
    /// </summary>
968

    
969
    public class XsltUsingSourceResolver : Example
970
    {
971

    
972
        public override string testName
973
        {
974
            get { return "XsltUsingSourceResolver"; }
975
        }
976

    
977
        public override void run(Uri samplesDir)
978
        {
979

    
980
            // Create a Processor instance.
981
            Processor processor = new Processor();
982

    
983
            // Load the source document
984
            DocumentBuilder builder = processor.NewDocumentBuilder();
985
            UserXmlResolver buildTimeResolver = new UserXmlResolver();
986
            buildTimeResolver.Message = "** Calling build-time XmlResolver: ";
987
            builder.XmlResolver = buildTimeResolver;
988
            builder.BaseUri = samplesDir;
989

    
990
            String doc = "<!DOCTYPE doc [<!ENTITY e SYSTEM 'flamingo.txt'>]><doc>&e;</doc>";
991
            MemoryStream ms = new MemoryStream();
992
            StreamWriter tw = new StreamWriter(ms);
993
            tw.Write(doc);
994
            tw.Flush();
995
            Stream instr = new MemoryStream(ms.GetBuffer(), 0, (int)ms.Length);
996
            XdmNode input = builder.Build(instr);
997

    
998
            // Create a transformer for the stylesheet.
999
            String stylesheet =
1000
                "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='2.0'>" +
1001
                "<xsl:import href='empty.xslt'/>" +
1002
                "<xsl:template match='/'>" +
1003
                "<out note=\"{doc('heron.txt')}\" ><xsl:copy-of select='.'/></out>" +
1004
                "</xsl:template>" +
1005
                "</xsl:stylesheet>";
1006

    
1007
            XsltCompiler compiler = processor.NewXsltCompiler();
1008
            UserXmlResolver compileTimeResolver = new UserXmlResolver();
1009
            compileTimeResolver.Message = "** Calling compile-time XmlResolver: ";
1010
            compiler.XmlResolver = compileTimeResolver;
1011
            compiler.BaseUri = samplesDir;
1012
            Xslt30Transformer transformer = compiler.Compile(new XmlTextReader(new StringReader(stylesheet))).Load30();
1013

    
1014
            // Set the user-written XmlResolver
1015
            UserXmlResolver runTimeResolver = new UserXmlResolver();
1016
            runTimeResolver.Message = "** Calling transformation-time XmlResolver: ";
1017
            transformer.InputXmlResolver = runTimeResolver;
1018

    
1019
            // Create a serializer
1020
            Serializer serializer = processor.NewSerializer();
1021
            serializer.SetOutputWriter(Console.Out);
1022

    
1023
            // Transform the source XML and serialize the result document
1024
            transformer.ApplyTemplates(input, serializer);
1025

    
1026
        }
1027
    }
1028

    
1029
    /// <summary>
1030
    /// Run an XSLT transformation displaying compile-time errors to the console
1031
    /// </summary>
1032

    
1033
    public class XsltDisplayingErrors : Example
1034
    {
1035

    
1036
        public override string testName
1037
        {
1038
            get { return "XsltDisplayingErrors"; }
1039
        }
1040

    
1041
        public override void run(Uri samplesDir)
1042
        {
1043
            // Create a Processor instance.
1044
            Processor processor = new Processor();
1045

    
1046
            // Create the XSLT Compiler
1047
            XsltCompiler compiler = processor.NewXsltCompiler();
1048

    
1049

    
1050
            // Define a stylesheet containing errors
1051
            String stylesheet =
1052
                "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>\n" +
1053
                "<xsl:template name='eee:template'>\n" +
1054
                "  <xsl:value-of select='32'/>\n" +
1055
                "</xsl:template>\n" +
1056
                "<xsl:template name='main'>\n" +
1057
                "  <xsl:value-of select='$var'/>\n" +
1058
                "</xsl:template>\n" +
1059
                "</xsl:stylesheet>";
1060

    
1061

    
1062
            // Attempt to compile the stylesheet and display the errors
1063
            try
1064
            {
1065
                compiler.BaseUri = new Uri("http://localhost/stylesheet");
1066
                compiler.Compile(new XmlTextReader(new StringReader(stylesheet)));
1067
                Console.WriteLine("Stylesheet compilation succeeded");
1068
            }
1069
            catch (Exception)
1070
            {
1071
                Console.WriteLine("Stylesheet compilation failed");
1072
            }
1073

    
1074

    
1075
        }
1076
    }
1077

    
1078
    /// <summary>
1079
    /// Run an XSLT transformation capturing compile-time errors within the application
1080
    /// </summary>
1081

    
1082
    public class XsltCapturingErrors : Example
1083
    {
1084

    
1085
        public override string testName
1086
        {
1087
            get { return "XsltCapturingErrors"; }
1088
        }
1089

    
1090
        public override void run(Uri samplesDir)
1091
        {
1092
            // Create a Processor instance.
1093
            Processor processor = new Processor();
1094

    
1095
            // Create the XSLT Compiler
1096
            XsltCompiler compiler = processor.NewXsltCompiler();
1097

    
1098
            // Create a list to hold the error information
1099
            compiler.ErrorList = new List<StaticError>();
1100

    
1101
            // Define a stylesheet containing errors
1102
            String stylesheet =
1103
                "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>\n" +
1104
                "<xsl:template name='fff:template'>\n" +
1105
                "  <xsl:value-of select='32'/>\n" +
1106
                "</xsl:template>\n" +
1107
                "<xsl:template name='main'>\n" +
1108
                "  <xsl:value-of select='$var'/>\n" +
1109
                "</xsl:template>\n" +
1110
                "</xsl:stylesheet>";
1111

    
1112

    
1113
            // Attempt to compile the stylesheet and display the errors
1114
            try
1115
            {
1116
                compiler.BaseUri = new Uri("http://localhost/stylesheet");
1117
                compiler.Compile(new StringReader(stylesheet));
1118
                Console.WriteLine("Stylesheet compilation succeeded");
1119
            }
1120
            catch (Exception)
1121
            {
1122
                Console.WriteLine("Stylesheet compilation failed with " + compiler.ErrorList.Count + " errors");
1123
                foreach (StaticError error in compiler.ErrorList)
1124
                {
1125
                    Console.WriteLine("At line " + error.LineNumber + ": " + error.Message);
1126
                }
1127
            }
1128
        }
1129
    }
1130

    
1131
    /// <summary>
1132
    /// Run an XSLT transformation capturing run-time messages within the application
1133
    /// </summary>
1134

    
1135
    public class XsltCapturingMessages : Example
1136
    {
1137

    
1138
        public override string testName
1139
        {
1140
            get { return "XsltCapturingMessages"; }
1141
        }
1142

    
1143
        public override void run(Uri samplesDir)
1144
        {
1145

    
1146
            // Create a Processor instance.
1147
            Processor processor = new Processor();
1148

    
1149
            // Create the XSLT Compiler
1150
            XsltCompiler compiler = processor.NewXsltCompiler();
1151

    
1152
            // Define a stylesheet that generates messages
1153
            String stylesheet =
1154
                "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='2.0'>\n" +
1155
                "<xsl:template name='main'>\n" +
1156
                "  <xsl:message><a>starting</a></xsl:message>\n" +
1157
                "  <out><xsl:value-of select='current-date()'/></out>\n" +
1158
                "  <xsl:message><a>finishing</a></xsl:message>\n" +
1159
                "</xsl:template>\n" +
1160
                "</xsl:stylesheet>";
1161

    
1162
            compiler.BaseUri = new Uri("http://localhost/stylesheet");
1163
            XsltExecutable exec = compiler.Compile(new StringReader(stylesheet));
1164

    
1165

    
1166
            // Create a transformer for the stylesheet.
1167
            Xslt30Transformer transformer = exec.Load30();
1168

    
1169
            // Create a Listener to which messages will be written
1170
            transformer.MessageListener = new UserMessageListener();
1171

    
1172
            // Create a serializer, with output to the standard output stream
1173
            Serializer serializer = processor.NewSerializer();
1174
            serializer.SetOutputWriter(Console.Out);
1175

    
1176
            // Transform the source XML, calling a named initial template, and serialize the result document
1177
            transformer.CallTemplate(new QName("", "main"), serializer);
1178
        }
1179

    
1180
    }
1181

    
1182
    ///
1183
    /// Example user-written message listener
1184
    ///
1185

    
1186
    public class UserMessageListener : IMessageListener
1187
    {
1188

    
1189
        public void Message(XdmNode content, bool terminate, IXmlLocation location)
1190
        {
1191
            Console.Out.WriteLine("MESSAGE terminate=" + (terminate ? "yes" : "no") + " at " + DateTime.Now);
1192
            Console.Out.WriteLine("From instruction at line " + location.LineNumber +
1193
                    " of " + location.BaseUri);
1194
            Console.Out.WriteLine(">>" + content.StringValue);
1195
        }
1196
    }
1197

    
1198

    
1199
    /// <summary>
1200
    /// Run an XSLT transformation showing source line numbers
1201
    /// </summary>
1202

    
1203
    public class XsltShowingLineNumbers : Example
1204
    {
1205

    
1206
        public override string testName
1207
        {
1208
            get { return "XsltShowingLineNumbers"; }
1209
        }
1210

    
1211
        public override void run(Uri samplesDir)
1212
        {
1213

    
1214
            // Create a Processor instance.
1215
            Processor processor = new Processor(true);
1216

    
1217
            // Ask for the JAXP parser to be used (or not to be used, if false)
1218
            processor.SetProperty("http://saxon.sf.net/feature/preferJaxpParser", "false");
1219

    
1220
            // Load the source document
1221
            DocumentBuilder builder = processor.NewDocumentBuilder();
1222
            builder.IsLineNumbering = true;
1223
            XdmNode input = builder.Build(new Uri(samplesDir, "data/othello.xml"));
1224

    
1225
            // Create the XSLT Compiler
1226
            XsltCompiler compiler = processor.NewXsltCompiler();
1227

    
1228
            // Define a stylesheet that shows line numbers of source elements
1229
            String stylesheet =
1230
                "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='2.0' xmlns:saxon='http://saxon.sf.net/'>\n" +
1231
                "<xsl:template match='/'>\n" +
1232
                "<out>\n" +
1233
                "  <xsl:for-each select='//ACT'>\n" +
1234
                "  <out><xsl:value-of select='saxon:line-number(.)'/></out>\n" +
1235
                "  </xsl:for-each>\n" +
1236
                "</out>\n" +
1237
                "</xsl:template>\n" +
1238
                "</xsl:stylesheet>";
1239

    
1240
            compiler.BaseUri = new Uri("http://localhost/stylesheet");
1241
            XsltExecutable exec = compiler.Compile(new StringReader(stylesheet));
1242

    
1243

    
1244
            // Create a transformer for the stylesheet.
1245
            Xslt30Transformer transformer = exec.Load30();
1246

    
1247
            // Create a serializer, with output to the standard output stream
1248
            Serializer serializer = processor.NewSerializer();
1249
            serializer.SetOutputWriter(Console.Out);
1250

    
1251
            // Transform the source XML and serialize the result document
1252
            transformer.ApplyTemplates(input, serializer);
1253
        }
1254

    
1255
    }
1256

    
1257
    /// <summary>
1258
    /// Run an XSLT transformation producing multiple output documents
1259
    /// </summary>
1260

    
1261
    public class XsltMultipleOutput : Example
1262
    {
1263

    
1264
        public override string testName
1265
        {
1266
            get { return "XsltMultipleOutput"; }
1267
        }
1268

    
1269
        public override void run(Uri samplesDir)
1270
        {
1271
            // Create a Processor instance.
1272
            Processor processor = new Processor();
1273
            processor.SetProperty("http://saxon.sf.net/feature/timing", "true");
1274

    
1275
            // Load the source document
1276
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/othello.xml"));
1277

    
1278
            // Create a transformer for the stylesheet.
1279
            Xslt30Transformer transformer = processor.NewXsltCompiler().Compile(new Uri(samplesDir, "styles/play.xsl")).Load30();
1280

    
1281
            // Set the required stylesheet parameter
1282
            Dictionary<QName, XdmValue> parameters = new Dictionary<QName, XdmValue>();
1283
            parameters.Add(new QName("", "", "dir"), new XdmAtomicValue(samplesDir.ToString() + "play"));
1284
            transformer.SetStylesheetParameters(parameters);
1285

    
1286
            // Create a serializer, with output to the standard output stream
1287
            Serializer serializer = processor.NewSerializer();
1288
            serializer.SetOutputWriter(Console.Out);
1289

    
1290
            // Transform the source XML and serialize the result document
1291
            transformer.ApplyTemplates(input, serializer);
1292

    
1293
        }
1294

    
1295
    }
1296

    
1297

    
1298
    /// <summary>
1299
    /// Run an XSLT transformation using the id() function, with DTD validation
1300
    /// </summary>
1301

    
1302
    public class XsltUsingIdFunction : Example
1303
    {
1304

    
1305
        public override string testName
1306
        {
1307
            get { return "XsltUsingIdFunction"; }
1308
        }
1309

    
1310
        public override void run(Uri samplesDir)
1311
        {
1312
            // Create a Processor instance
1313
            Processor processor = new Processor();
1314

    
1315
            // Load the source document. The Microsoft .NET parser does not report attributes of type ID. The only
1316
            // way to use the function is therefore (a) to use a different parser, or (b) to use xml:id instead. We
1317
            // choose the latter course.
1318

    
1319
            String doc = "<!DOCTYPE table [" +
1320
                "<!ELEMENT table (row*)>" +
1321
                "<!ELEMENT row EMPTY>" +
1322
                "<!ATTLIST row xml:id ID #REQUIRED>" +
1323
                "<!ATTLIST row value CDATA #REQUIRED>]>" +
1324
                "<table><row xml:id='A123' value='green'/><row xml:id='Z789' value='blue'/></table>";
1325

    
1326
            DocumentBuilder builder = processor.NewDocumentBuilder();
1327
            builder.DtdValidation = true;
1328
            builder.BaseUri = samplesDir;
1329
            MemoryStream ms = new MemoryStream();
1330
            StreamWriter tw = new StreamWriter(ms);
1331
            tw.Write(doc);
1332
            tw.Flush();
1333
            Stream instr = new MemoryStream(ms.GetBuffer(), 0, (int)ms.Length);
1334
            XdmNode input = builder.Build(instr);
1335

    
1336
            // Define a stylesheet that uses the id() function
1337
            String stylesheet =
1338
                "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='2.0'>\n" +
1339
                "<xsl:template match='/'>\n" +
1340
                "  <xsl:copy-of select=\"id('Z789')\"/>\n" +
1341
                "</xsl:template>\n" +
1342
                "</xsl:stylesheet>";
1343

    
1344
            XsltCompiler compiler = processor.NewXsltCompiler();
1345
            compiler.BaseUri = new Uri("http://localhost/stylesheet");
1346
            XsltExecutable exec = compiler.Compile(new StringReader(stylesheet));
1347

    
1348
            // Create a transformer for the stylesheet
1349
            Xslt30Transformer transformer = exec.Load30();
1350

    
1351
            // Set the destination
1352
            XdmDestination results = new XdmDestination();
1353

    
1354
            // Transform the XML
1355
            transformer.ApplyTemplates(input, results);
1356

    
1357
            // Show the result
1358
            Console.WriteLine(results.XdmNode.ToString());
1359

    
1360
        }
1361

    
1362
    }
1363

    
1364
    /// <summary>
1365
    /// Show a transformation using a user-written result document handler. This example
1366
    /// captures each of the result documents in a DOM, and creates a Hashtable that indexes
1367
    /// the DOM trees according to their absolute URI. On completion, it writes all the DOMs
1368
    /// to the standard output.
1369
    /// </summary>
1370

    
1371
    public class XsltUsingResultHandler : Example
1372
    {
1373

    
1374
        public override string testName
1375
        {
1376
            get { return "XsltUsingResultHandler"; }
1377
        }
1378

    
1379
        public override void run(Uri samplesDir)
1380
        {
1381
            // Create a Processor instance.
1382
            Processor processor = new Processor();
1383

    
1384
            // Load the source document
1385
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/othello.xml"));
1386

    
1387
            // Define a stylesheet that splits the document up
1388
            String stylesheet =
1389
                "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='2.0'>\n" +
1390
                "<xsl:template match='/'>\n" +
1391
                "  <xsl:for-each select='//ACT'>\n" +
1392
                "    <xsl:result-document href='{position()}.xml'>\n" +
1393
                "      <xsl:copy-of select='TITLE'/>\n" +
1394
                "    </xsl:result-document>\n" +
1395
                "  </xsl:for-each>\n" +
1396
                "</xsl:template>\n" +
1397
                "</xsl:stylesheet>";
1398

    
1399
            XsltCompiler compiler = processor.NewXsltCompiler();
1400
            compiler.BaseUri = new Uri("http://localhost/stylesheet");
1401
            XsltExecutable exec = compiler.Compile(new StringReader(stylesheet));
1402

    
1403
            // Create a transformer for the stylesheet.
1404
            Xslt30Transformer transformer = exec.Load30();
1405

    
1406
            // Establish the result document handler
1407
            Hashtable results = new Hashtable();
1408
            transformer.ResultDocumentHandler = new UserResultDocumentHandler(results);
1409

    
1410
            // Transform the source XML to a NullDestination (because we only want the secondary result files).
1411
            NullDestination destination = new NullDestination();
1412
            destination.BaseUri = samplesDir;
1413
            transformer.ApplyTemplates(input, destination);
1414

    
1415
            // Process the captured DOM results
1416
            foreach (DictionaryEntry entry in results)
1417
            {
1418
                string uri = (string)entry.Key;
1419
                Console.WriteLine("\nResult File " + uri);
1420
                DomDestination dom = (DomDestination)results[uri];
1421
                Console.Write(dom.XmlDocument.OuterXml);
1422
            }
1423

    
1424
        }
1425

    
1426
    }
1427

    
1428
    /// <summary>
1429
    /// Show a transformation using a registered collection
1430
    /// </summary>
1431

    
1432
    public class XsltUsingRegisteredCollection : Example
1433
    {
1434

    
1435
        public override string testName
1436
        {
1437
            get { return "XsltUsingRegisteredCollection"; }
1438
        }
1439

    
1440
        public override void run(Uri samplesDir)
1441
        {
1442
            // Create a Processor instance.
1443
            Processor processor = new Processor();
1444

    
1445
            // Define a stylesheet that uses the collection() function
1446
            String stylesheet =
1447
                "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='2.0'>\n" +
1448
                "<xsl:template name='main'>\n" +
1449
                " <out>\n" +
1450
                "  <xsl:for-each select=\"collection('http://www.example.org/my-collection')\">\n" +
1451
                "    <document uri='{document-uri(.)}' nodes='{count(//*)}'/>\n" +
1452
                "  </xsl:for-each><zzz/>\n" +
1453
                "  <xsl:for-each select=\"collection('http://www.example.org/my-collection')\">\n" +
1454
                "    <document uri='{document-uri(.)}' nodes='{count(//*)}'/>\n" +
1455
                "  </xsl:for-each>\n" +
1456
                " </out>\n" +
1457
                "</xsl:template>\n" +
1458
                "</xsl:stylesheet>";
1459

    
1460
            // Register a named collection
1461
            Uri[] documentList = new Uri[2];
1462
            documentList[0] = new Uri(samplesDir, "data/othello.xml");
1463
            documentList[1] = new Uri(samplesDir, "data/books.xml");
1464
            processor.RegisterCollection(new Uri("http://www.example.org/my-collection"), documentList);
1465

    
1466
            XsltCompiler compiler = processor.NewXsltCompiler();
1467
            compiler.BaseUri = new Uri("http://localhost/stylesheet");
1468
            XsltExecutable exec = compiler.Compile(new StringReader(stylesheet));
1469

    
1470
            // Create a transformer for the stylesheet.
1471
            Xslt30Transformer transformer = exec.Load30();
1472

    
1473
            // Set the destination
1474
            XdmDestination results = new XdmDestination();
1475

    
1476
            // Transform the XML, calling a named initial template
1477
            transformer.CallTemplate(new QName("", "main"), results);
1478

    
1479
            // Show the result
1480
            Console.WriteLine(results.XdmNode.ToString());
1481

    
1482
        }
1483
    }
1484

    
1485
    /// <summary>
1486
    /// Show a transformation using a collection that maps to a directory
1487
    /// </summary>
1488

    
1489
    public class XsltUsingDirectoryCollection : Example
1490
    {
1491

    
1492
        public override string testName
1493
        {
1494
            get { return "XsltUsingDirectoryCollection"; }
1495
        }
1496

    
1497
        public override void run(Uri samplesDir)
1498
        {
1499
            // Create a Processor instance.
1500
            Processor processor = new Processor();
1501

    
1502
            // Define a stylesheet that uses the collection() function
1503
            String stylesheet =
1504
                "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='2.0'>\n" +
1505
                "<xsl:template name='main'>\n" +
1506
                " <out>\n" +
1507
                "  <xsl:for-each select=\"collection('" + samplesDir + "?recurse=yes;select=*.xml;on-error=warning')\">\n" +
1508
                "    <document uri='{document-uri(.)}' nodes='{count(//*)}'/>\n" +
1509
                "  </xsl:for-each><zzz/>\n" +
1510
                " </out>\n" +
1511
                "</xsl:template>\n" +
1512
                "</xsl:stylesheet>";
1513

    
1514

    
1515
            XsltCompiler compiler = processor.NewXsltCompiler();
1516
            compiler.BaseUri = new Uri("http://localhost/stylesheet");
1517
            XsltExecutable exec = compiler.Compile(new StringReader(stylesheet));
1518

    
1519
            // Create a transformer for the stylesheet.
1520
            Xslt30Transformer transformer = exec.Load30();
1521

    
1522
            // Set the destination
1523
            XdmDestination results = new XdmDestination();
1524

    
1525
            // Transform the XML, calling a named initial template
1526
            transformer.CallTemplate(new QName("", "main"), results);
1527

    
1528
            // Show the result
1529
            Console.WriteLine(results.XdmNode.ToString());
1530

    
1531
        }
1532

    
1533
    }
1534

    
1535
    /// <summary>
1536
    /// Demonstrate XSLT extensibility using user-written reflexive extension functions
1537
    /// </summary>
1538
    /// <remarks>Note: If SamplesExtensions is compiled to a different assembly than ExamplesPE, use 
1539
    /// the namespace URI clitype:SampleExtensions.SampleExtensions?asm=ASSEMBLY_NAME_HERE
1540
    /// Alternatively, the location of an assembly can be provided as a URI using the 'from' keyword
1541
    /// e.g. clitype:SampleExtensions.SampleExtensions?from=file:///c:/lib/SampleExtensions.dll
1542
    /// </remarks>
1543

    
1544
    public class XsltExtensibility : Example
1545
    {
1546

    
1547
        public override string testName
1548
        {
1549
            get { return "XsltExtensibility"; }
1550
        }
1551

    
1552
        public override void run(Uri samplesDir)
1553
        {
1554
            // Create a Processor instance.
1555
            Processor processor = new Processor(true);
1556

    
1557
            // Identify the Processor version
1558
            Console.WriteLine(processor.ProductVersion);
1559

    
1560
            // Set diagnostics
1561
            //processor.SetProperty("http://saxon.sf.net/feature/trace-external-functions", "true");
1562

    
1563
            // Create the stylesheet
1564
            String s = @"<xsl:transform version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
1565
                @" xmlns:ext='clitype:SampleExtensions.SampleExtensions?asm=ExamplesPE' " +
1566
                @" xmlns:tz='clitype:System.TimeZone' " +
1567
                @" exclude-result-prefixes='ext tz'> " +
1568
                @" <xsl:param name='timezone' required='yes'/> " +
1569
                @" <xsl:template match='/'> " +
1570
                @" <out addition='{ext:add(2,2)}' " +
1571
                @" average='{ext:average((1,2,3,4,5,6))}' " +
1572
                @" firstchild='{ext:nameOfFirstChild(.)}' " +
1573
                @" timezone='{tz:StandardName($timezone)}' >" +
1574
                @" <xsl:copy-of select='ext:FirstChild((//ITEM)[1])'/> " +
1575
                @" <combine1><xsl:sequence select='ext:combine(ext:FirstChild((//ITEM)[1]), count(*))'/></combine1> " +
1576
                @" <combine2><xsl:sequence select='ext:combine((//TITLE)[1], (//AUTHOR)[1])'/></combine2> " +
1577
                @" </out> " +
1578
                @" </xsl:template></xsl:transform>";
1579

    
1580
            // Create a transformer for the stylesheet.
1581
            Xslt30Transformer transformer = processor.NewXsltCompiler().Compile(new StringReader(s)).Load30();
1582

    
1583
            // Load the source document (must be a wrapper around an XmlDocument for this test)
1584
            XmlDocument doc = new XmlDocument();
1585
            doc.Load(new XmlTextReader(samplesDir.AbsolutePath + "data/books.xml"));
1586
            XdmNode input = processor.NewDocumentBuilder().Wrap(doc);
1587

    
1588
            // Supply a parameter
1589
            Dictionary<QName, XdmValue> parameters = new Dictionary<QName, XdmValue>();
1590
            parameters.Add(new QName("", "timezone"), new XdmExternalObjectValue(TimeZone.CurrentTimeZone));
1591
            transformer.SetStylesheetParameters(parameters);
1592

    
1593
            // Create a serializer, with output to the standard output stream
1594
            Serializer serializer = processor.NewSerializer();
1595
            serializer.SetOutputWriter(Console.Out);
1596
            serializer.SetOutputProperty(Serializer.INDENT, "yes");
1597

    
1598
            // Transform the source XML and serialize the result document
1599
            transformer.ApplyTemplates(input, serializer);
1600
        }
1601

    
1602
    }
1603

    
1604
    /// <summary>
1605
    /// Show a transformation using calls to integrated extension functions (full API)
1606
    /// </summary>
1607

    
1608
    public class XsltIntegratedExtension : Example
1609
    {
1610

    
1611
        public override string testName
1612
        {
1613
            get { return "XsltIntegratedExtension"; }
1614
        }
1615

    
1616
        public override void run(Uri samplesDir)
1617
        {
1618

    
1619
            // Create a Processor instance.
1620
            Processor processor = new Processor();
1621

    
1622
            // Identify the Processor version
1623
            Console.WriteLine(processor.ProductVersion);
1624

    
1625
            // Set diagnostics
1626
            //processor.SetProperty("http://saxon.sf.net/feature/trace-external-functions", "true");
1627

    
1628
            // Create the stylesheet
1629
            String s = @"<xsl:transform version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
1630
                @" xmlns:math='http://example.math.co.uk/demo' " +
1631
                @" xmlns:env='http://example.env.co.uk/demo' " +
1632
                @" exclude-result-prefixes='math env'> " +
1633
                @" <xsl:template name='go'> " +
1634
                @" <out sqrt2='{math:sqrt(2.0e0)}' " +
1635
                @" defaultNamespace='{env:defaultNamespace()}' " +
1636
                @" sqrtEmpty='{math:sqrt(())}'> " +
1637
                @" <defaultNS value='{env:defaultNamespace()}' xsl:xpath-default-namespace='http://default.namespace.com/' /> " +
1638
                @" </out> " +
1639
                @" </xsl:template></xsl:transform>";
1640

    
1641
            // Register the integrated extension functions math:sqrt and env:defaultNamespace
1642
            processor.RegisterExtensionFunction(new Sqrt());
1643
            processor.RegisterExtensionFunction(new DefaultNamespace());
1644

    
1645
            // Create a transformer for the stylesheet.
1646
            Xslt30Transformer transformer = processor.NewXsltCompiler().Compile(new StringReader(s)).Load30();
1647

    
1648
            // Create a serializer, with output to the standard output stream
1649
            Serializer serializer = processor.NewSerializer();
1650
            serializer.SetOutputWriter(Console.Out);
1651
            serializer.SetOutputProperty(Serializer.INDENT, "yes");
1652

    
1653
            // Transform the source XML, calling a named initial template, and serialize the result document
1654
            transformer.CallTemplate(new QName("go"), serializer);
1655
        }
1656

    
1657
    }
1658

    
1659
    /// <summary>
1660
    /// Example extension function to compute a square root, using the full API
1661
    /// </summary>
1662

    
1663
    public class Sqrt : ExtensionFunctionDefinition
1664
    {
1665
        public override QName FunctionName
1666
        {
1667
            get
1668
            {
1669
                return new QName("http://example.math.co.uk/demo", "sqrt");
1670
            }
1671
        }
1672

    
1673
        public override int MinimumNumberOfArguments
1674
        {
1675
            get
1676
            {
1677
                return 1;
1678
            }
1679
        }
1680

    
1681
        public override int MaximumNumberOfArguments
1682
        {
1683
            get
1684
            {
1685
                return 1;
1686
            }
1687
        }
1688

    
1689
        public override XdmSequenceType[] ArgumentTypes
1690
        {
1691
            get
1692
            {
1693
                return new XdmSequenceType[]{
1694
                    new XdmSequenceType(XdmAtomicType.BuiltInAtomicType(QName.XS_DOUBLE), '?')
1695
                };
1696
            }
1697
        }
1698

    
1699
        public override XdmSequenceType ResultType(XdmSequenceType[] ArgumentTypes)
1700
        {
1701
            return new XdmSequenceType(XdmAtomicType.BuiltInAtomicType(QName.XS_DOUBLE), '?');
1702
        }
1703

    
1704
        public override bool TrustResultType
1705
        {
1706
            get
1707
            {
1708
                return true;
1709
            }
1710
        }
1711

    
1712

    
1713
        public override ExtensionFunctionCall MakeFunctionCall()
1714
        {
1715
            return new SqrtCall();
1716
        }
1717
    }
1718

    
1719
    internal class SqrtCall : ExtensionFunctionCall
1720
    {
1721
        public override IEnumerator<XdmItem> Call(IEnumerator<XdmItem>[] arguments, DynamicContext context)
1722
        {
1723
            Boolean exists = arguments[0].MoveNext();
1724
            if (exists)
1725
            {
1726
                XdmAtomicValue arg = (XdmAtomicValue)arguments[0].Current;
1727
                double val = (double)arg.Value;
1728
                double sqrt = System.Math.Sqrt(val);
1729
                return new XdmAtomicValue(sqrt).GetEnumerator();
1730
            }
1731
            else
1732
            {
1733
                return EmptyEnumerator<XdmItem>.INSTANCE;
1734
            }
1735
        }
1736
    }
1737

    
1738
    /// <summary>
1739
    /// Example extension function to return the default namespace from the static context
1740
    /// </summary>
1741

    
1742
    public class DefaultNamespace : ExtensionFunctionDefinition
1743
    {
1744
        public override QName FunctionName
1745
        {
1746
            get
1747
            {
1748
                return new QName("http://example.env.co.uk/demo", "defaultNamespace");
1749
            }
1750
        }
1751

    
1752
        public override int MinimumNumberOfArguments
1753
        {
1754
            get
1755
            {
1756
                return 0;
1757
            }
1758
        }
1759

    
1760
        public override int MaximumNumberOfArguments
1761
        {
1762
            get
1763
            {
1764
                return 0;
1765
            }
1766
        }
1767

    
1768
        public override XdmSequenceType[] ArgumentTypes
1769
        {
1770
            get
1771
            {
1772
                return new XdmSequenceType[] { };
1773
            }
1774
        }
1775

    
1776
        public override bool DependsOnFocus
1777
        {
1778
            get
1779
            {
1780
                return true;
1781
                // actually it depends on the static context rather than the focus; but returning true is necessary
1782
                // to avoid the call being extracted to a global variable.
1783
            }
1784
        }
1785

    
1786
        public override XdmSequenceType ResultType(XdmSequenceType[] ArgumentTypes)
1787
        {
1788
            return new XdmSequenceType(XdmAtomicType.BuiltInAtomicType(QName.XS_STRING), '?');
1789
        }
1790

    
1791
        public override bool TrustResultType
1792
        {
1793
            get
1794
            {
1795
                return true;
1796
            }
1797
        }
1798

    
1799
        public override ExtensionFunctionCall MakeFunctionCall()
1800
        {
1801
            return new DefaultNamespaceCall();
1802
        }
1803
    }
1804

    
1805
    internal class DefaultNamespaceCall : ExtensionFunctionCall
1806
    {
1807
        private string defaultNamespace;
1808

    
1809
        public override void SupplyStaticContext(StaticContext context)
1810
        {
1811
            defaultNamespace = context.GetNamespaceForPrefix("");
1812
        }
1813

    
1814
        public override IEnumerator<XdmItem> Call(IEnumerator<XdmItem>[] arguments, DynamicContext context)
1815
        {
1816
            if (defaultNamespace != null)
1817
            {
1818
                return new XdmAtomicValue(defaultNamespace).GetEnumerator();
1819
            }
1820
            else
1821
            {
1822
                return EmptyEnumerator<XdmItem>.INSTANCE;
1823
            }
1824
        }
1825
    }
1826

    
1827
    /// <summary>
1828
    /// Show a transformation using calls to an integrated extension function (simple API)
1829
    /// </summary>
1830

    
1831
    public class XsltSimpleExtension : Example
1832
    {
1833

    
1834
        public override string testName
1835
        {
1836
            get { return "XsltSimpleExtension"; }
1837
        }
1838

    
1839
        public override void run(Uri samplesDir)
1840
        {
1841

    
1842
            // Create a Processor instance.
1843
            Processor processor = new Processor();
1844

    
1845
            // Identify the Processor version
1846
            Console.WriteLine(processor.ProductVersion);
1847

    
1848
            // Set diagnostics
1849
            //processor.SetProperty("http://saxon.sf.net/feature/trace-external-functions", "true");
1850

    
1851
            // Create the stylesheet
1852
            String s = @"<xsl:transform version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
1853
                @" xmlns:math='http://example.math.co.uk/demo'> " +
1854
                @" <xsl:template name='go'> " +
1855
                @" <out sqrt2='{math:sqrtSimple(2.0e0)}' " +
1856
                @" sqrtEmpty='{math:sqrtSimple(())}'/> " +
1857
                @" </xsl:template></xsl:transform>";
1858

    
1859
            // Register the integrated extension function math:sqrtSimple
1860
            processor.RegisterExtensionFunction(new SqrtSimple());
1861

    
1862
            // Create a transformer for the stylesheet.
1863
            Xslt30Transformer transformer = processor.NewXsltCompiler().Compile(new StringReader(s)).Load30();
1864

    
1865
            // Create a serializer, with output to the standard output stream
1866
            Serializer serializer = processor.NewSerializer();
1867
            serializer.SetOutputWriter(Console.Out);
1868
            serializer.SetOutputProperty(Serializer.INDENT, "yes");
1869

    
1870
            // Transform the source XML, calling a named initial template, and serialize the result document
1871
            transformer.CallTemplate(new QName("go"), serializer);
1872
        }
1873

    
1874
    }
1875

    
1876
    /// <summary>
1877
    /// Example extension function to compute a square root, using the simple API
1878
    /// </summary>
1879

    
1880
    public class SqrtSimple : ExtensionFunction
1881
    {
1882
        public XdmValue Call(XdmValue[] arguments)
1883
        {
1884
            if (!(arguments[0] is XdmEmptySequence))
1885
            {
1886
                XdmAtomicValue arg = (XdmAtomicValue)arguments[0].ItemAt(0);
1887
                double val = (double)arg.Value;
1888
                double sqrt = System.Math.Sqrt(val);
1889
                return new XdmAtomicValue(sqrt);
1890
            }
1891
            else
1892
            {
1893
                return XdmValue.MakeValue((double)0);
1894
            }
1895
        }
1896

    
1897
        public XdmSequenceType[] GetArgumentTypes()
1898
        {
1899
            return new XdmSequenceType[]{
1900
                new XdmSequenceType(XdmAtomicType.BuiltInAtomicType(QName.XS_DOUBLE), '?')
1901
            };
1902
        }
1903

    
1904
        public QName GetName()
1905
        {
1906
            return new QName("http://example.math.co.uk/demo", "sqrtSimple");
1907
        }
1908

    
1909
        public XdmSequenceType GetResultType()
1910
        {
1911
            return new XdmSequenceType(XdmAtomicType.BuiltInAtomicType(QName.XS_DOUBLE), ' ');
1912
        }
1913
    }
1914

    
1915
    /// <summary>
1916
    /// Show a query producing a document as its result and serializing this to a FileStream
1917
    /// </summary>
1918

    
1919
    public class XQueryToStream : Example
1920
    {
1921

    
1922
        public override string testName
1923
        {
1924
            get { return "XQueryToStream"; }
1925
        }
1926

    
1927
        public override void run(Uri samplesDir)
1928
        {
1929
            Processor processor = new Processor(true);
1930
            XQueryCompiler compiler = processor.NewXQueryCompiler();
1931
            compiler.BaseUri = samplesDir.ToString();
1932
            compiler.DeclareNamespace("saxon", "http://saxon.sf.net/");
1933
            XQueryExecutable exp = compiler.Compile("<saxon:example>{static-base-uri()}</saxon:example>");
1934
            XQueryEvaluator eval = exp.Load();
1935
            Serializer qout = processor.NewSerializer();
1936
            qout.SetOutputProperty(Serializer.METHOD, "xml");
1937
            qout.SetOutputProperty(Serializer.INDENT, "yes");
1938
            qout.SetOutputProperty(Serializer.SAXON_INDENT_SPACES, "1");
1939
            qout.SetOutputStream(new FileStream("testoutput.xml", FileMode.Create, FileAccess.Write));
1940
            Console.WriteLine("Output written to testoutput.xml");
1941
            eval.Run(qout);
1942
        }
1943

    
1944
    }
1945

    
1946
    /// <summary>
1947
    /// Show a query producing a single atomic value as its result and returning the value
1948
    /// to the C# application
1949
    /// </summary>
1950

    
1951
    public class XQueryToAtomicValue : Example
1952
    {
1953

    
1954
        public override string testName
1955
        {
1956
            get { return "XQueryToAtomicValue"; }
1957
        }
1958

    
1959
        public override void run(Uri samplesDir)
1960
        {
1961
            Processor processor = new Processor();
1962
            XQueryCompiler compiler = processor.NewXQueryCompiler();
1963
            XQueryExecutable exp = compiler.Compile("avg(for $i in 1 to 10 return $i * $i)");
1964
            XQueryEvaluator eval = exp.Load();
1965
            XdmAtomicValue result = (XdmAtomicValue)eval.EvaluateSingle();
1966
            Console.WriteLine("Result type: " + result.Value.GetType());
1967
            Console.WriteLine("Result value: " + (decimal)result.Value);
1968
        }
1969

    
1970
    }
1971

    
1972
    /// <summary>
1973
    /// Show a query producing a sequence as its result and returning the sequence
1974
    /// to the C# application in the form of an iterator. For each item in the
1975
    /// result, its string value is output.
1976
    /// </summary>
1977

    
1978
    public class XQueryToSequence : Example
1979
    {
1980

    
1981
        public override string testName
1982
        {
1983
            get { return "XQueryToSequence"; }
1984
        }
1985

    
1986
        public override void run(Uri samplesDir)
1987
        {
1988
            Processor processor = new Processor();
1989
            XQueryCompiler compiler = processor.NewXQueryCompiler();
1990
            XQueryExecutable exp = compiler.Compile("for $i in 1 to 10 return $i * $i");
1991
            XQueryEvaluator eval = exp.Load();
1992
            XdmValue value = eval.Evaluate();
1993
            foreach(XdmItem item in value)
1994
            {
1995
                Console.WriteLine(item.ToString());
1996
            }
1997

    
1998
        }
1999

    
2000
    }
2001

    
2002
    /// <summary>
2003
    /// Show a query producing a DOM as its input and producing a DOM as its output
2004
    /// </summary>
2005

    
2006
    public class XQueryToDom : Example
2007
    {
2008

    
2009
        public override string testName
2010
        {
2011
            get { return "XQueryToDom"; }
2012
        }
2013

    
2014
        public override void run(Uri samplesDir)
2015
        {
2016
            Processor processor = new Processor();
2017

    
2018
            XmlDocument input = new XmlDocument();
2019
            input.Load(new Uri(samplesDir, "data/books.xml").ToString());
2020
            XdmNode indoc = processor.NewDocumentBuilder().Build(new XmlNodeReader(input));
2021

    
2022
            XQueryCompiler compiler = processor.NewXQueryCompiler();
2023
            XQueryExecutable exp = compiler.Compile("<doc>{reverse(/*/*)}</doc>");
2024
            XQueryEvaluator eval = exp.Load();
2025
            eval.ContextItem = indoc;
2026
            DomDestination qout = new DomDestination();
2027
            eval.Run(qout);
2028
            XmlDocument outdoc = qout.XmlDocument;
2029
            Console.WriteLine(outdoc.OuterXml);
2030
        }
2031

    
2032
    }
2033

    
2034
    /// <summary>
2035
    /// Show a query producing a Saxon tree as its input and producing a Saxon tree as its output
2036
    /// </summary>
2037

    
2038
    public class XQueryToXdm : Example
2039
    {
2040

    
2041
        public override string testName
2042
        {
2043
            get { return "XQueryToXdm"; }
2044
        }
2045

    
2046
        public override void run(Uri samplesDir)
2047
        {
2048
            Processor processor = new Processor();
2049

    
2050
            DocumentBuilder loader = processor.NewDocumentBuilder();
2051
            loader.BaseUri = new Uri(samplesDir, "data/books.xml");
2052
            XdmNode indoc = loader.Build(loader.BaseUri);
2053

    
2054
            XQueryCompiler compiler = processor.NewXQueryCompiler();
2055
            XQueryExecutable exp = compiler.Compile("<doc>{reverse(/*/*)}</doc>");
2056
            XQueryEvaluator eval = exp.Load();
2057
            eval.ContextItem = indoc;
2058
            XdmDestination qout = new XdmDestination();
2059
            eval.Run(qout);
2060
            XdmNode outdoc = qout.XdmNode;
2061
            Console.WriteLine(outdoc.OuterXml);
2062
        }
2063

    
2064
    }
2065

    
2066
    /// <summary>
2067
    /// Show a query making a direct call to a user-defined function defined in the query
2068
    /// </summary>
2069

    
2070
    public class XQueryCallFunction : Example
2071
    {
2072

    
2073
        public override string testName
2074
        {
2075
            get { return "XQueryCallFunction"; }
2076
        }
2077

    
2078
        public override void run(Uri samplesDir)
2079
        {
2080
            Processor processor = new Processor();
2081

    
2082
            XQueryCompiler qc = processor.NewXQueryCompiler();
2083
            Uri uri = new Uri(samplesDir, "data/books.xml");
2084
            XQueryExecutable exp1 = qc.Compile("declare namespace f='f.ns';" +
2085
                   "declare variable $z := 1 + xs:integer(doc-available('" + uri.ToString() + "'));" +
2086
                   "declare variable $p as xs:integer external;" +
2087
                   "declare function f:t1($v1 as xs:integer) { " +
2088
                   "   $v1 div $z + $p" +
2089
                   "};" +
2090
                   "10");
2091
            XQueryEvaluator ev = exp1.Load();
2092
            ev.SetExternalVariable(new QName("", "p"), new XdmAtomicValue(39));
2093
            XdmValue v1 = new XdmAtomicValue(10);
2094
            XdmValue result = ev.CallFunction(new QName("f.ns", "f:t1"), new XdmValue[] { v1 });
2095
            Console.WriteLine("First result (expected 44): " + result.ToString());
2096
            v1 = new XdmAtomicValue(20);
2097
            result = ev.CallFunction(new QName("f.ns", "f:t1"), new XdmValue[] { v1 });
2098
            Console.WriteLine("Second result (expected 49): " + result.ToString());
2099
        }
2100

    
2101
    }
2102

    
2103
    /// <summary>
2104
    /// Show a query reading an input document using an XmlReader (the .NET XML parser)
2105
    /// </summary>
2106

    
2107
    public class XQueryFromXmlReader : Example
2108
    {
2109

    
2110
        public override string testName
2111
        {
2112
            get { return "XQueryFromXmlReader"; }
2113
        }
2114

    
2115
        public override void run(Uri samplesDir)
2116
        {
2117
            Processor processor = new Processor();
2118

    
2119
            String inputFileName = new Uri(samplesDir, "data/books.xml").ToString();
2120
            XmlTextReader reader = new XmlTextReader(inputFileName,
2121
                UriConnection.getReadableUriStream(new Uri(samplesDir, "data/books.xml")));
2122
            reader.Normalization = true;
2123

    
2124
            // Add a validating reader - needed in case there are entity references
2125
            XmlReaderSettings settings = new XmlReaderSettings();
2126
            settings.ValidationType = ValidationType.DTD;
2127
            settings.DtdProcessing = DtdProcessing.Parse;
2128
            XmlReader validator = XmlReader.Create(reader, settings);
2129

    
2130
            XdmNode doc = processor.NewDocumentBuilder().Build(validator);
2131

    
2132
            XQueryCompiler compiler = processor.NewXQueryCompiler();
2133
            XQueryExecutable exp = compiler.Compile("/");
2134
            XQueryEvaluator eval = exp.Load();
2135
            eval.ContextItem = doc;
2136
            Serializer qout = processor.NewSerializer();
2137
            qout.SetOutputProperty(Serializer.METHOD, "xml");
2138
            qout.SetOutputProperty(Serializer.INDENT, "yes");
2139
            qout.SetOutputStream(new FileStream("testoutput2.xml", FileMode.Create, FileAccess.Write));
2140
            Console.WriteLine("Output written to testoutput2.xml");
2141
            eval.Run(qout);
2142
        }
2143

    
2144
    }
2145

    
2146
    /// <summary>
2147
    /// Show a query producing a sequence as its result and returning the sequence
2148
    /// to the C# application in the form of an iterator. The sequence is then
2149
    /// output by serializing each item individually, with each item on a new line.
2150
    /// </summary>
2151

    
2152
    public class XQueryToSerializedSequence : Example
2153
    {
2154

    
2155
        public override string testName
2156
        {
2157
            get { return "XQueryToSerializedSequence"; }
2158
        }
2159

    
2160
        public override void run(Uri samplesDir)
2161
        {
2162
            Processor processor = new Processor();
2163
            String inputFileName = new Uri(samplesDir, "data/books.xml").ToString();
2164
            XmlTextReader reader = new XmlTextReader(inputFileName,
2165
                UriConnection.getReadableUriStream(new Uri(samplesDir, "data/books.xml")));
2166
            reader.Normalization = true;
2167

    
2168
            // Add a validating reader - needed in case there are entity references
2169
            XmlReaderSettings settings = new XmlReaderSettings();
2170
            settings.ValidationType = ValidationType.DTD;
2171
            settings.DtdProcessing = DtdProcessing.Parse;
2172
            XmlReader validator = XmlReader.Create(reader, settings);
2173

    
2174
            XdmNode doc = processor.NewDocumentBuilder().Build(reader);
2175

    
2176
            XQueryCompiler compiler = processor.NewXQueryCompiler();
2177
            XQueryExecutable exp = compiler.Compile("//ISBN");
2178
            XQueryEvaluator eval = exp.Load();
2179
            eval.ContextItem = doc;
2180

    
2181
            foreach (XdmNode node in eval)
2182
            {
2183
                Console.WriteLine(node.OuterXml);
2184
            }
2185
        }
2186

    
2187
    }
2188

    
2189
    /// <summary>
2190
    /// Show a query that takes a parameter (external variable) as input.
2191
    /// The query produces a single atomic value as its result and returns the value
2192
    /// to the C# application. 
2193
    /// </summary>
2194

    
2195
    public class XQueryUsingParameter : Example
2196
    {
2197

    
2198
        public override string testName
2199
        {
2200
            get { return "XQueryUsingParameter"; }
2201
        }
2202

    
2203
        public override void run(Uri samplesDir)
2204
        {
2205
            Processor processor = new Processor();
2206
            XQueryCompiler compiler = processor.NewXQueryCompiler();
2207
            compiler.DeclareNamespace("p", "http://saxon.sf.net/ns/p");
2208
            XQueryExecutable exp = compiler.Compile(
2209
                    "declare variable $p:in as xs:integer external; $p:in * $p:in");
2210
            XQueryEvaluator eval = exp.Load();
2211
            eval.SetExternalVariable(new QName("http://saxon.sf.net/ns/p", "p:in"), new XdmAtomicValue(12));
2212
            XdmAtomicValue result = (XdmAtomicValue)eval.EvaluateSingle();
2213
            Console.WriteLine("Result type: " + result.Value.GetType());
2214
            Console.WriteLine("Result value: " + (long)result.Value);
2215
        }
2216

    
2217
    }
2218

    
2219
    /// <summary>
2220
    /// Show a query consisting of two modules, using a QueryResolver to resolve
2221
    /// the "import module" declaration
2222
    /// </summary>
2223

    
2224
    public class XQueryMultiModule : Example
2225
    {
2226

    
2227
        public override string testName
2228
        {
2229
            get { return "XQueryMultiModule"; }
2230
        }
2231

    
2232
        public override void run(Uri samplesDir)
2233
        {
2234

    
2235
            String mod1 = "import module namespace m2 = 'http://www.example.com/module2';" +
2236
                          "m2:square(3)";
2237

    
2238
            String mod2 = "module namespace m2 = 'http://www.example.com/module2';" +
2239
                          "declare function m2:square($p) { $p * $p };";
2240

    
2241
            Processor processor = new Processor();
2242
            XQueryCompiler compiler = processor.NewXQueryCompiler();
2243

    
2244
            InlineModuleResolver resolver = new InlineModuleResolver();
2245
            resolver.AddModule(new Uri("http://www.example.com/module2"), mod2);
2246
            compiler.QueryResolver = resolver;
2247
            XQueryExecutable exp = compiler.Compile(mod1);
2248
            XQueryEvaluator eval = exp.Load();
2249

    
2250
            XdmAtomicValue result = (XdmAtomicValue)eval.EvaluateSingle();
2251
            Console.WriteLine("Result type: " + result.Value.GetType());
2252
            Console.WriteLine("Result value: " + (long)result.Value);
2253
        }
2254

    
2255
        // A simple QueryResolver designed to show that the actual query
2256
        // text can come from anywhere: in this case, the resolver maintains
2257
        // a simple mapping of module URIs onto strings.
2258

    
2259
        public class InlineModuleResolver : IQueryResolver
2260
        {
2261

    
2262
            private Hashtable modules = new Hashtable();
2263

    
2264
            public void AddModule(Uri moduleName, String moduleText)
2265
            {
2266
                modules.Add(moduleName, moduleText);
2267
            }
2268

    
2269
            public Uri[] GetModules(String moduleUri, Uri baseUri, String[] locationHints)
2270
            {
2271
                Uri[] result = { new Uri(moduleUri) };
2272
                return result;
2273
            }
2274

    
2275
            public Object GetEntity(Uri absoluteUri)
2276
            {
2277
                return modules[absoluteUri];
2278
            }
2279
        }
2280

    
2281
    }
2282

    
2283
    /// <summary>
2284
    /// Demonstrate using a try-catch expression in the query, a feature of XQuery 3.0
2285
    /// </summary>
2286

    
2287
    public class XQueryTryCatch : Example
2288
    {
2289

    
2290
        public override string testName
2291
        {
2292
            get { return "XQueryTryCatch"; }
2293
        }
2294

    
2295
        public override void run(Uri samplesDir)
2296
        {
2297

    
2298
            String query = "xquery version '3.0'; try {doc('book.xml')}catch * {\"XQuery 3.0 catch clause - file not found.\"}";
2299
            Processor processor = new Processor();
2300

    
2301
            XQueryCompiler compiler = processor.NewXQueryCompiler();
2302
            compiler.XQueryLanguageVersion = "3.0";
2303
            XQueryExecutable exp = compiler.Compile(query);
2304
            XQueryEvaluator eval = exp.Load();
2305
            Serializer qout = processor.NewSerializer(Console.Out);
2306
            eval.Run(qout);
2307
        }
2308

    
2309
    }
2310

    
2311
    /// <summary>
2312
    /// Demonstrate XQuery extensibility using user-written reflexive extension functions
2313
    /// </summary>
2314
    /// <remarks>Note: If SamplesExtensions is compiled to a different assembly than ExamplesPE, use 
2315
    /// the namespace URI clitype:SampleExtensions.SampleExtensions?asm=ASSEMBLY_NAME_HERE
2316
    /// Alternatively, the location of an assembly can be provided as a URI using the 'from' keyword
2317
    /// e.g. clitype:SampleExtensions.SampleExtensions?from=file:///c:/lib/SampleExtensions.dll
2318
    /// </remarks>
2319

    
2320
    public class XQueryExtensibility : Example
2321
    {
2322

    
2323
        public override string testName
2324
        {
2325
            get { return "XQueryExtensibility"; }
2326
        }
2327

    
2328
        public override void run(Uri samplesDir)
2329
        {
2330
            String query =
2331
                "declare namespace ext = \"clitype:SampleExtensions.SampleExtensions?asm=ExamplesPE\";" +
2332
                "<out>" +
2333
                "  <addition>{ext:add(2,2)}</addition>" +
2334
                "  <average>{ext:average((1,2,3,4,5,6))}</average>" +
2335
                "  <language>{ext:hostLanguage()}</language>" +
2336
                "</out>";
2337

    
2338
            Processor processor = new Processor(true);
2339
            XQueryCompiler compiler = processor.NewXQueryCompiler();
2340
            XQueryExecutable exp = compiler.Compile(query);
2341
            XQueryEvaluator eval = exp.Load();
2342
            Serializer qout = processor.NewSerializer(Console.Out);
2343
            eval.Run(qout);
2344
        }
2345

    
2346
    }
2347

    
2348

    
2349
    public class UriConnection
2350
    {
2351

    
2352
        // Get a stream for reading from a file:// URI
2353

    
2354
        public static Stream getReadableUriStream(Uri uri)
2355
        {
2356
            WebRequest request = (WebRequest)WebRequest.Create(uri);
2357
            return request.GetResponse().GetResponseStream();
2358
        }
2359

    
2360
        // Get a stream for writing to a file:// URI
2361

    
2362
        public static Stream getWritableUriStream(Uri uri)
2363
        {
2364
            FileWebRequest request = (FileWebRequest)WebRequest.CreateDefault(uri);
2365
            request.Method = "POST";
2366
            return request.GetRequestStream();
2367
        }
2368
    }
2369

    
2370
    ///
2371
    /// A sample XmlResolver. In the case of a URI ending with ".txt", it returns the
2372
    /// URI itself, wrapped as an XML document. In the case of the URI "empty.xslt", it returns an empty
2373
    /// stylesheet. In all other cases, it returns null, which has the effect of delegating
2374
    /// processing to the standard XmlResolver.
2375
    ///
2376

    
2377
    public class UserXmlResolver : XmlUrlResolver
2378
    {
2379

    
2380
        public String Message = null;
2381

    
2382
        public override object GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
2383
        {
2384
            if (Message != null)
2385
            {
2386
                Console.WriteLine(Message + absoluteUri + " (role=" + role + ")");
2387
            }
2388

    
2389
            if (absoluteUri.ToString().EndsWith(".txt"))
2390
            {
2391
                MemoryStream ms = new MemoryStream();
2392
                StreamWriter tw = new StreamWriter(ms);
2393
                tw.Write("<uri>");
2394
                tw.Write(absoluteUri);
2395
                tw.Write("</uri>");
2396
                tw.Flush();
2397
                return new MemoryStream(ms.GetBuffer(), 0, (int)ms.Length);
2398
            }
2399
            if (absoluteUri.ToString().EndsWith("empty.xslt"))
2400
            {
2401
                String ss = "<transform xmlns='http://www.w3.org/1999/XSL/Transform' version='2.0'/>";
2402
                MemoryStream ms = new MemoryStream();
2403
                StreamWriter tw = new StreamWriter(ms);
2404
                tw.Write(ss);
2405
                tw.Flush();
2406
                return new MemoryStream(ms.GetBuffer(), 0, (int)ms.Length);
2407
            }
2408
            else
2409
            {
2410
                return null;
2411
            }
2412
        }
2413
    }
2414

    
2415
    public class UserResultDocumentHandler : IResultDocumentHandler
2416
    {
2417

    
2418
        private Hashtable results;
2419

    
2420
        public UserResultDocumentHandler(Hashtable table)
2421
        {
2422
            this.results = table;
2423
        }
2424

    
2425
        public XmlDestination HandleResultDocument(string href, Uri baseUri)
2426
        {
2427
            DomDestination destination = new DomDestination();
2428
            results[href] = destination;
2429
            return destination;
2430
        }
2431

    
2432
    }
2433
}
2434

    
2435

    
2436
//
2437
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
2438
// you may not use this file except in compliance with the License. You may obtain a copy of the
2439
// License at http://www.mozilla.org/MPL/
2440
//
2441
// Software distributed under the License is distributed on an "AS IS" basis,
2442
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
2443
// See the License for the specific language governing rights and limitations under the License.
2444
//
2445
// The Original Code is: all this file.
2446
//
2447
// The Initial Developer of the Original Code is Michael H. Kay.
2448
//
2449
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
2450
//
2451
// Contributor(s): none.
2452
//
2453

    
(3-3/5)