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();
        }
    }
Actions #1

Updated by O'Neil Delpratt over 5 years ago

Yes this is a bug. I have managed to reproduce the error message.

Actions #2

Updated by O'Neil Delpratt over 5 years ago

There ha been significant changes to the XmlDestination and how we manage the sub-classes such as the Serializer in Saxon 9.9. These changes we hope are not too disruptive for users.

Actions #3

Updated by Martin Honnen over 5 years ago

As I am not getting anywhere trying to use Saxon 9.8 .NET and XsltTransformer and ResultDocumentHandler to handle xsl:result-document I will probably have to wait for the 9.9 release. Is there any date on the release or if the public APIs are at least already stable is there any chance to get the API doc of 9.9 online? Will Xslt30Transformer in 9.9 provide a way to handle xsl:result-document so that it is no longer necessary to rely on XsltTransformer for that?

Actions #4

Updated by O'Neil Delpratt over 5 years ago

  • Status changed from New to In Progress
  • Applies to branch 9.9 added

Update,

The only difference on the Saxon 9.9 is that the Serializer can only be created via the Processor. This is now inline with how it is done on the Java platform. I can confirm that we are getting the same error on Saxon 9.9 for .NET. Investigating the problem further.

Actions #5

Updated by O'Neil Delpratt over 5 years ago

The issue is the handling of ResultDocuments on .NET relies on IResultDocumentHandler interface, which works with a OutputURIResolver class on Java. The OutputURIResolver interface from Saxon 9.9 is obsolescent. It is unable to handle the full flexibility of XSLT 3.0, for example it cannot handle raw output, JSON serialization, or the item-separator serialization property.

I will look to port the new mechanism on Java to .NET.

Actions #6

Updated by O'Neil Delpratt over 5 years ago

  • Status changed from In Progress to Resolved
  • Fix Committed on Branch 9.9 added

Bug fixed on the Saxon 9.9 branch.

Actions #7

Updated by O'Neil Delpratt about 5 years ago

  • % Done changed from 0 to 100
  • Fixed in Maintenance Release 9.9.1.1 added

Bug fix applied to the Saxon 9.9.1.1 maintenance release.

Actions #8

Updated by O'Neil Delpratt about 5 years ago

  • Status changed from Resolved to Closed
Actions #9

Updated by Michael Kay about 5 years ago

  • Priority changed from High to Normal

Please register to edit this issue

Also available in: Atom PDF