Project

Profile

Help

Support #5646

open

Question about streamable [Saxon 11.4]

Added by Radu Coravu 4 months ago. Updated 3 months ago.

Status:
New
Priority:
Low
Assignee:
-
Category:
-
Sprint/Milestone:
-
Start date:
2022-08-17
Due date:
% Done:

0%

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

Description

Looking at this code "net.sf.saxon.s9api.AbstractXsltTransformer.applyTemplatesToSource(Source, Receiver)" it appears that if the initial mode is streamable the streaming templates are applied even if the transformer is created without using the "com.saxonica.config.StreamingTransformerFactory". I think this was not the case in older Saxon 10 and 9 versions. Will this error message "net.sf.saxon.trans.XsltController.warningIfStreamable(Mode)" ever be issued in this case?

Actions #1

Updated by Radu Coravu 4 months ago

Also is it worth creating a com.saxonica.config.StreamingTransformerFactory.StreamingTransformerFactory(EnterpriseConfiguration) to create a transformer with streaming if evem transformers created by a plain transformer factory can now auto detect and enter streaming mode?

Actions #2

Updated by Michael Kay 4 months ago

The StreamingTransformerFactory was introduced because the default TransformerFactory is required to conform closely to the JAXP specifications (this is to ensure that applications expecting to run with Xalan don't break if you put Saxon on the classpath). This means that the "source" of the transformation is both the target of the initial (implicit) apply-templates instruction, and the global context item. If the initial context item is a streamable document, and this is referenced in any global variable, then the transformation becomes non-streamable. The StreamingTransformerFactory therefore gives you the ability to run a streaming transformation by breaking the JAXP rule that the target of the initial apply-templates is also the context item for global variables.

This does raise the question, are we now breaking the JAXP contract in the way we run a (regular, default) TransformerFactory? That depends a bit on how you read JAXP, and how it's supposed to behave if the TransformerFactory returns a 2.0 or 3.0 processor. The JAXP spec tends to be hopelessly under-specified on such questions, and the real test is, how likely is it that an application that expects to be running Xalan will break if you put Saxon on the classpath? If it's a 1.0 stylesheet, then we would like it to work unchanged wherever possible (it's not possible, of course, if it uses Xalan extensions). If it's a 3.0 stylesheet that specifies streamable="yes", then I'm not too concerned.

Actions #3

Updated by Radu Coravu 4 months ago

I think it's pretty decent right now that the regular transformer factory has some kind of auto detection for streaming modes. We have a checkbox in Oxygen which is supposed to enable streaming and when checked it creates a "StreamingTransformerFactory", otherwise we create a plain TransformerFactory. But after the Saxon 11 changes this checkbox does not seem to make a lot of sense, even if unchecked, Saxon still does streaming if appropriate. So I'm not sure if to remove the checkbox or not as our auto tests which asserted that streaming is not done when that checkbox is unchecked now fail as Saxon will do streaming anyway.

Actions #4

Updated by Michael Kay 3 months ago

I ran this test on 11.x and it didn't use streaming:

@Test
    public void testStreamingViaDefaultFactory() {

        try {
            String xsl =
                    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                            "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n" +
                            "    xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n" +
                            "    exclude-result-prefixes=\"xs\"\n" +
                            "    version=\"3.0\">\n"
                            + "<xsl:mode streamable=\"true\"/>\n" +
                            "    <xsl:template match=\"*:person\"><xsl:value-of select=\"@id\"/></xsl:template>\n" +
                            "</xsl:stylesheet>";
            String xml = "<person id='test'/>";

            TransformerFactory factory = new SaxonTransformerFactory();
            Transformer transformer = factory.newTransformer(new StreamSource(new StringReader(xsl)));
            transformer.setErrorListener(new StandardErrorListener() {
                @Override
                public void warning(TransformerException exception) {
                    System.err.println(exception.getMessage());
                    fail();
                }
            });

            InputSource inputSource = new InputSource(new StringReader(xml));
            SAXSource xmlSource = new SAXSource(inputSource);
            StringWriter writer = new StringWriter();
            transformer.transform(xmlSource, new StreamResult(writer));

            System.out.println(writer);
        } catch (TransformerException e) {
            e.printStackTrace();
            fail();
        }
    }

The same is true if I use an EnterpriseTransformerFactory. But If you change it to use the StreamingTransformerFactory then it does use streaming.

So I think that using a StreamingTransformerFactory does make a difference.

Actions #5

Updated by Radu Coravu 3 months ago

Thanks, we decided to preserve our advanced Saxon XSLT processor setting which enables the use of the StreamingTransformerFactory instead of the EnterpriseTransformerFactory.

Please register to edit this issue

Also available in: Atom PDF