Project

Profile

Help

Bug #4088

closed

Serialization with ResultDocumentHandler doesn't take output properties defined with "format" attribute and "xsl:output" or directly as attributes of "xsl:result-document" into account

Added by Martin Honnen over 5 years ago. Updated about 5 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Category:
.NET API
Sprint/Milestone:
-
Start date:
2019-01-08
Due date:
% Done:

100%

Estimated time:
Legacy ID:
Applies to branch:
9.8, 9.9
Fix Committed on Branch:
9.9
Fixed in Maintenance Release:
Platforms:

Description

This is related to https://saxonica.plan.io/issues/4087 but I file this as a separate issue as I am now convinced this is a bug (various samples run fine when used with Java, both from the command line and the API, and with .NET from the command line and the API without using ResultDocumentHandler but fail with ResultDocumentHandler):

It seems Saxon .NET's XsltTransformer, when using an assigned ResultDocumentHandler, doesn't take any serialization properties of the xsl:result-document into account, neither those defined in a named xsl:output referenced with the format attribute nor those specified directly like e.g. method="json", instead it looks like a default XML serialization is used in all cases.

That means any attempt to use e.g. method="json" with maps or arrays fails with "SENR0001: Cannot serialize a map using the xml method".

Example XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output method="html" indent="yes" html-version="5"/>

  <xsl:template match="/" name="xsl:initial-template">
    <html>
      <head>
        <title>Test</title>
      </head>
      <body>
        <h1>Test</h1>
      </body>
    </html>

    <xsl:result-document href="result-1.json" method="json" indent="yes">
      <xsl:sequence select="map { 'name' : 'foo', 'values' : [ 'a', 'b', 'c' ] }"/>
    </xsl:result-document>
    
  </xsl:template>

</xsl:stylesheet>

C#

        static void Main(string[] args)
        {
            TestXsltFromURL(Path.Combine(Directory.GetCurrentDirectory(), "output-method-json-test1.xsl"));
        }

        static void TestXsltFromURL(string xslURL)
        {
            Processor proc = new Processor(false);

            XsltTransformer transformer = proc.NewXsltCompiler().Compile(new Uri(xslURL)).Load();

            transformer.InitialTemplate = new QName("http://www.w3.org/1999/XSL/Transform", "initial-template");

            transformer.Run(proc.NewSerializer(Console.Out));

            Console.WriteLine();

            MyResultDocumentHandler resDocHandler = new MyResultDocumentHandler(proc);

            transformer.ResultDocumentHandler = resDocHandler;

            transformer.Run(proc.NewSerializer(Console.Out));

            foreach (MySerializer ser in resDocHandler.Serializers)
            {
                Console.WriteLine("{0}:\n{1}", ser.Href, ser.Result);
                Console.WriteLine();
            }

        }

gives

Error at char 6 in xsl:sequence/@select on line 20 column 84 of output-method-json-test1.xsl:
  SENR0001: Cannot serialize a map using the xml method
Saxon.Api.DynamicError
  HResult=0x80131500
  Message=Cannot serialize a map using the xml method
  Source=saxon9he-api
  StackTrace:
   at Saxon.Api.XsltTransformer.Run(XmlDestination destination)
   at ResultDocDocTypeMissing.Program.TestXsltFromURL(String xslURL) in C:\SomePath\ResultDocDocTypeMissing\ResultDocDocTypeMissing\Program.cs:line 34
   at ResultDocDocTypeMissing.Program.Main(String[] args) in C:\SomePath\ResultDocDocTypeMissing\ResultDocDocTypeMissing\Program.cs:line 15

Line 34 is the second transformer.Run(proc.NewSerializer(Console.Out)); call, after the transformer.ResultDocumentHandler = resDocHandler; has been set.

Used classes are:

   internal class MyResultDocumentHandler : IResultDocumentHandler
    {
        private Processor proc;

        public List<MySerializer> Serializers { get; set; }

        public MyResultDocumentHandler(Processor proc)
        {
            this.proc = proc;
            Serializers = new List<MySerializer>();
        }

        public XmlDestination HandleResultDocument(string href, Uri baseUri)
        {
            var ser = new MySerializer(proc, href);
            Serializers.Add(ser);
            return ser;
        }
    }

    internal class MySerializer : Serializer
    {
        private StringWriter resultWriter;

        public string Result { get; private set; }

        public string Href { get; }

        public MySerializer(Processor processor, string href)
        {
            SetProcessor(processor);

            Href = href;

            resultWriter = new StringWriter();

            SetOutputWriter(resultWriter);

        }

        public override void Close()
        {
            Result = resultWriter.ToString();
            resultWriter.Close();
            resultWriter.Dispose();
            base.Close();
        }
    }

Please register to edit this issue

Also available in: Atom PDF