Menu

#76 Usage of Xslt30Transformer class

v1.0_(example)
open
nobody
1
2015-10-14
2015-10-14
Anonymous
No

Hi,

I have been using saxon9he older version for valdiating my XML files.
I downloaded the latest SaxonHE 9.6.0.7. I was struggling to make my existing code use Xslt30Transformer class for transformation instead of its old counterpart XsltTransformer.
Is it possible for you to share some sample code snippet to show how to use Xslt30Transformer for validating an XML file using a XSLT file.

Appreciate your help.

Regards

Discussion

  • Michael Kay

    Michael Kay - 2015-10-14

    You might find some of our test cases helpful, see attached.

    In future, we're not using SourceForge for support any more. Please use http://saxonica.plan.io

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Copyright (c) 2014 Saxonica Limited.
    // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
    // If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
    // This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    package s9apitest;

    import jaxptest.ConfigTest;
    import junit.framework.TestCase;
    import net.sf.saxon.Configuration;
    import net.sf.saxon.functions.AccessorFn;
    import net.sf.saxon.lib.FeatureKeys;
    import net.sf.saxon.om.NodeInfo;
    import net.sf.saxon.om.StructuredQName;
    import net.sf.saxon.option.jdom.JDOMNodeWrapper;
    import net.sf.saxon.option.jdom.JDOMObjectModel;
    import net.sf.saxon.option.jdom2.JDOM2ObjectModel;
    import net.sf.saxon.option.xom.XOMDocumentWrapper;
    import net.sf.saxon.option.xom.XOMObjectModel;
    import net.sf.saxon.s9api.*;
    import net.sf.saxon.trans.XPathException;
    import net.sf.saxon.type.ComplexType;
    import net.sf.saxon.type.SchemaException;
    import net.sf.saxon.type.SchemaType;
    import net.sf.saxon.value.Cardinality;
    import net.sf.saxon.value.QNameValue;
    import org.xml.sax.InputSource;

    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.transform.ErrorListener;
    import javax.xml.transform.Source;
    import javax.xml.transform.TransformerException;
    import javax.xml.transform.URIResolver;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.sax.SAXSource;
    import javax.xml.transform.stream.StreamSource;
    import java.io.;
    import java.util.
    ;

    /
    * JUnit tests for the s9api Xslt30Transformer

    * @author Michael Kay
    * @date March 2015
    /
    public class TestXslt30Transformer extends TestCase {

    /**
     * Simple test
     */
    
    public void testSimple() {
        // Create a Processor instance.
        try {
            Processor processor = new Processor(false);
            processor.setConfigurationProperty("http://saxon.sf.net/feature/timing", "true");
    
            // Create a transformer for the stylesheet.
            Xslt30Transformer transformer = processor.newXsltCompiler().compile(
                    new StreamSource(new File(ConfigTest.DATA_DIR + "caffo/Transform2.xslt"))).load30();
    
            // Create a serializer
            XdmDestination serializer = new XdmDestination();
            long start = new Date().getTime();
    
            // Transform the source XML to System.out.
            for (int i = 0; i < 10; i++) {
                // Load the source document
                XdmNode input = processor.newDocumentBuilder().build(
                        new File(ConfigTest.DATA_DIR + "caffo/Input.xml"));
                // Set the root node of the source document to be the initial context node
                transformer.applyTemplates(input, serializer);
            }
    
            long end = new Date().getTime();
            System.err.println("Av Time: " + (end - start) / 10 + "ms");
        } catch (SaxonApiException e) {
            e.printStackTrace();
            fail(e.getMessage());
        }
    
    }
    
    /**
     * Test for the case where the context item is not the root
     */
    
    public void testContextNotRoot() {
        try {
            Processor proc = new Processor(false);
            StringReader sr = new StringReader("<doc><e>text</e></doc>");
            SAXSource source = new SAXSource(new InputSource(sr));
            DocumentBuilder builder = proc.newDocumentBuilder();
            XdmNode node = builder.build(source);
            XsltCompiler xqcomp = proc.newXsltCompiler();
            sr = new StringReader("<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" +
                    "<xsl:variable name='x' select='.'/>" +
                    "<xsl:template match='/'>errorA</xsl:template>" +
                    "<xsl:template match='e'>[<xsl:value-of select='name($x)'/>]</xsl:template>" +
                    "</xsl:stylesheet>");
            SAXSource style = new SAXSource(new InputSource(sr));
            Xslt30Transformer trans = xqcomp.compile(style).load30();
    
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            Serializer serializer = proc.newSerializer(os);
    
            XdmSequenceIterator iter = node.axisIterator(Axis.DESCENDANT, new QName("e"));
            XdmNode e = (XdmNode) iter.next();
            trans.setGlobalContextItem(node);
            trans.applyTemplates(e, serializer);
    
            String result = os.toString();
            assertFalse("matched root", result.contains("errorA"));
            assertTrue("matched e", result.contains("[]"));
    
        } catch (SaxonApiException e) {
            fail(e.getMessage());
        }
    }
    
    /**
     * Test location information for run-time errors when stylesheet built as an XdmNode
     */
    
    public void testErrorLocationFromXdm() {
        try {
            // Norm Walsh reported getting line numbers > 2^20. Can't reproduce.
            Processor proc = new Processor(false);
            StringReader sr = new StringReader("<doc><e>text</e></doc>");
            SAXSource source = new SAXSource(new InputSource(sr));
            DocumentBuilder builder = proc.newDocumentBuilder();
            builder.setLineNumbering(true);
            XdmNode node = builder.build(source);
            XsltCompiler xqcomp = proc.newXsltCompiler();
    
            sr = new StringReader("<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>\n" +
                    "<xsl:import href='file:///" + ConfigTest.DATA_DIR + "identity.xsl'/>\n" +
                    "<xsl:import href='http://imported'/>\n" +
                    "<xsl:param name='x' select='0'/>\n" +
                    "<xsl:template match='/'>\n" +
                    "<xsl:apply-templates select='*'>\n" +
                    "<xsl:with-param name='p' select='()'/>\n" +
                    "</xsl:apply-templates>\n" +
                    "</xsl:template>\n" +
                    "</xsl:stylesheet>");
            XdmNode style2 = builder.build(new StreamSource(sr, "http://importer/"));
    
            sr = new StringReader("<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>\n" +
                    "<xsl:template match='e' as='node()'>\n" +
                    "<xsl:param name='x' select='0'/>\n" +
                    "<xsl:param name='p' as='node()*' select='()'/>\n" +
                    //"<e1/>" +
                    //"<e2/>" +
                    "<xsl:sequence select='$p'/>\n" +
                    "</xsl:template>\n" +
                    "</xsl:stylesheet>");
            final XdmNode style1 = builder.build(new StreamSource(sr, "http://imported/"));
    
            xqcomp.setURIResolver(new URIResolver() {
                public Source resolve(String href, String base) throws TransformerException {
                    if (href.startsWith("http:")) {
                        return style1.asSource();
                    } else {
                        return null;
                    }
                }
            });
    
            Xslt30Transformer trans = xqcomp.compile(style2.asSource()).load30();
    
            Serializer serializer = proc.newSerializer();
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            serializer.setOutputStream(os);
    
            trans.applyTemplates(node, serializer);
    
            fail("Transformation should fail");
    
        } catch (SaxonApiException e) {
            assertTrue("line=5", ((XPathException) e.getCause()).getLocator().getLineNumber() == 5);
        }
    }
    
    /**
     * Test created ErrorListener picks up errors in imported stylesheet
     */
    
    public void testErrorInImportedStylesheet() {
        final List<TransformerException> warnings = new ArrayList<TransformerException>(4);
        final List<TransformerException> errors = new ArrayList<TransformerException>(4);
        final List<TransformerException> fatals = new ArrayList<TransformerException>(4);
        ErrorListener listener = new ErrorListener() {
    
            public void warning(TransformerException exception) throws TransformerException {
                warnings.add(exception);
            }
    
            public void error(TransformerException exception) throws TransformerException {
                errors.add(exception);
            }
    
            public void fatalError(TransformerException exception) throws TransformerException {
                fatals.add(exception);
            }
    
        };
        try {
    
            Processor proc = new Processor(true);
    
            XsltCompiler xqcomp = proc.newXsltCompiler();
            xqcomp.setErrorListener(listener);
    
            Xslt30Transformer trans = xqcomp.compile(new StreamSource((new File(ConfigTest.DATA_DIR + "main.xsl")))).load30();
    
            Serializer serializer = proc.newSerializer();
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            serializer.setOutputStream(os);
    
            trans.callTemplate(new QName("main"), serializer);
    
            fail("Transformation should fail");
    
        } catch (SaxonApiException e) {
            assertTrue("warnings", warnings.isEmpty());
            assertTrue("errors", errors.isEmpty());
            assertTrue("fatals", fatals.size() > 0);
            //e.printStackTrace();
        }
    }
    
    /**
     * Test for the case where the context item is not the root, when starting at a named template
     */
    
    public void testContextNotRootNamedTemplate() {
        try {
            Processor proc = new Processor(false);
            StringReader sr = new StringReader("<doc><e>text</e></doc>");
            SAXSource source = new SAXSource(new InputSource(sr));
            DocumentBuilder builder = proc.newDocumentBuilder();
            XdmNode node = builder.build(source);
            XsltCompiler xqcomp = proc.newXsltCompiler();
            sr = new StringReader("<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" +
                    "<xsl:variable name='x' select='.'/>" +
                    "<xsl:template match='/'>errorA</xsl:template>" +
                    "<xsl:template name='main'>[<xsl:value-of select='name($x)'/>]</xsl:template>" +
                    "</xsl:stylesheet>");
            SAXSource style = new SAXSource(new InputSource(sr));
            Xslt30Transformer trans = xqcomp.compile(style).load30();
    
            Serializer serializer = proc.newSerializer();
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            serializer.setOutputStream(os);
    
            trans.setGlobalContextItem(node);
            trans.callTemplate(new QName("main"), serializer);
    
            String result = os.toString();
            assertFalse("matched root", result.contains("errorA"));
            assertTrue("matched e", result.contains("[]"));
    
        } catch (SaxonApiException e) {
            fail(e.getMessage());
        }
    }
    
    public void testUseAssociated() {
    
        try {
    
            Processor processor = new Processor(false);
    
            XsltCompiler compiler = processor.newXsltCompiler();
    
            String d = ConfigTest.DATA_DIR + "trax/";
    
            String foo_xml = d + "xml/foo.xml";
            Source sources =
                    compiler.getAssociatedStylesheet(new StreamSource(foo_xml), null,
                            null, null);
    
            Xslt30Transformer transformer = compiler.compile(sources).load30();
    
            transformer.applyTemplates(new StreamSource(foo_xml),
                    processor.newSerializer(System.out));
    
        } catch (SaxonApiException ex) {
            ex.printStackTrace();
            fail();
        }
    }
    
    /**
     * Build a document from a non-root element of a DOMSource
     */
    
    public void testNonRootDomSource() {
        try {
            Processor proc = new Processor(false);
            XsltCompiler comp = proc.newXsltCompiler();
            StringReader sr = new StringReader("<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" +
                    "<xsl:template match='/'>///<xsl:apply-templates/></xsl:template>" +
                    "<xsl:template match='*'>***<xsl:apply-templates/></xsl:template>" +
                    "</xsl:stylesheet>");
            XsltExecutable exec = comp.compile(new StreamSource(sr));
            Xslt30Transformer xsl = exec.load30();
            String in = "<?xml version='1.0'?> \n" +
                    "<doc><a><b/></a></doc>";
    
            // Read an XML file to a DOM
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            javax.xml.parsers.DocumentBuilder db = factory.newDocumentBuilder();
            InputSource is = new InputSource(new StringReader(in));
            org.w3c.dom.Document doc = db.parse(is);
            org.w3c.dom.Element ele = doc.getDocumentElement();
            StringWriter writer = new StringWriter();
            Serializer out = proc.newSerializer(writer);
            xsl.applyTemplates(new DOMSource(ele), out);
            assertFalse("started at element node", writer.toString().contains("///"));
        } catch (Exception e) {
            e.printStackTrace();
            fail(e.getMessage());
        }
    
    }
    
    /**
     * Send output to an XdmDestination
     */
    
    public void testXdmDestination() {
        try {
            Processor proc = new Processor(false);
            XsltCompiler comp = proc.newXsltCompiler();
            StringReader sr = new StringReader("<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" +
                    "<xsl:template name='go'><a/></xsl:template>" +
                    "</xsl:stylesheet>");
            XsltExecutable exec = comp.compile(new StreamSource(sr));
            Xslt30Transformer xsl = exec.load30();
            XdmDestination out = new XdmDestination();
            xsl.callTemplate(new QName("go"), out);
            XdmNode root = out.getXdmNode();
            assertTrue("result is document node", root.getNodeKind() == XdmNodeKind.DOCUMENT);
        } catch (Exception e) {
            e.printStackTrace();
            fail(e.getMessage());
        }
    
    }
    
    /**
     * Send output to a XOM tree
     */
    
    public void testXOMDestination() {
        try {
            Processor proc = new Processor(false);
            XsltCompiler comp = proc.newXsltCompiler();
            StringReader sr = new StringReader("<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" +
                    "<xsl:template name='go'><a/></xsl:template>" +
                    "</xsl:stylesheet>");
            XsltExecutable exec = comp.compile(new StreamSource(sr));
            Xslt30Transformer xsl = exec.load30();
            XdmDestination out = new XdmDestination();
            out.setTreeModel(XOMObjectModel.getInstance());
            xsl.callTemplate(new QName("go"), out);
            XdmNode root = out.getXdmNode();
            assertTrue("result is XOM document node", root.getUnderlyingNode() instanceof XOMDocumentWrapper);
        } catch (Exception e) {
            e.printStackTrace();
            fail(e.getMessage());
        }
    
    }
    
    /**
     * Send output to a JDOM tree
     */
    
    public void testJDOMDestination() {
        try {
            Processor proc = new Processor(false);
            XsltCompiler comp = proc.newXsltCompiler();
            StringReader sr = new StringReader("<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" +
                    "<xsl:template name='go'><a/></xsl:template>" +
                    "</xsl:stylesheet>");
            XsltExecutable exec = comp.compile(new StreamSource(sr));
            Xslt30Transformer xsl = exec.load30();
            XdmDestination out = new XdmDestination();
            out.setTreeModel(JDOMObjectModel.getInstance());
            xsl.callTemplate(new QName("go"), out);
            XdmNode root = out.getXdmNode();
            assertTrue("result is JDOM document node", root.getUnderlyingNode() instanceof JDOMNodeWrapper);
        } catch (Exception e) {
            e.printStackTrace();
            fail(e.getMessage());
        }
    
    }
    
    /**
     * Send output to a JDOM2 tree
     */
    
    public void testJDOM2Destination() {
        try {
            Processor proc = new Processor(false);
            XsltCompiler comp = proc.newXsltCompiler();
            StringReader sr = new StringReader("<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" +
                    "<xsl:template name='go'><a/></xsl:template>" +
                    "</xsl:stylesheet>");
            XsltExecutable exec = comp.compile(new StreamSource(sr));
            Xslt30Transformer xsl = exec.load30();
            XdmDestination out = new XdmDestination();
            out.setTreeModel(JDOM2ObjectModel.getInstance());
            xsl.callTemplate(new QName("go"), out);
            XdmNode root = out.getXdmNode();
            assertTrue("result is JDOM2 document node", root.getUnderlyingNode() instanceof net.sf.saxon.option.jdom2.JDOM2NodeWrapper);
        } catch (Exception e) {
            e.printStackTrace();
            fail(e.getMessage());
        }
    
    }
    
    public void testExtensionWithSchemaAccess() {
        // Create a Processor instance.
        try {
            Processor proc = new Processor(true);
            proc.setConfigurationProperty("http://saxon.sf.net/feature/timing", "true");
            XsltCompiler comp = proc.newXsltCompiler();
            comp.setSchemaAware(true);
            StringReader sr = new StringReader("<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:my='java:s9apitest.TestXslt30Transformer' exclude-result-prefixes='my'>" +
                    "<xsl:template match='*'><xsl:copy><xsl:copy-of select='@*'/><xsl:apply-templates/></xsl:copy></xsl:template>\n" +
                    "<xsl:template match='*/*/*/*[my:isOptional(.., node-name(.))]'/> \n" +
                    "</xsl:stylesheet>");
            XsltExecutable exec = comp.compile(new StreamSource(sr));
            Xslt30Transformer transformer = exec.load30();
    
            SchemaManager sm = proc.getSchemaManager();
            sm.load(new StreamSource(new File(ConfigTest.DATA_DIR + "books.xsd")));
            DocumentBuilder builder = proc.newDocumentBuilder();
            builder.setSchemaValidator(sm.newSchemaValidator());
            XdmNode books = builder.build(new File(ConfigTest.DATA_DIR + "books.xml"));
            // Create a serializer
            //String outfile = @"C:/MyJava/users/caffo/Output.xml";
            StringWriter sw = new StringWriter();
            Serializer serializer = proc.newSerializer(sw);
            serializer.setOutputProperty(Serializer.Property.INDENT, "yes");
            transformer.applyTemplates(books, serializer);
            assertTrue(sw.toString().contains("TITLE"));
            assertFalse(sw.toString().contains("AUTHOR"));
        } catch (SaxonApiException e) {
            e.printStackTrace();
            fail(e.getMessage());
        }
    
    }
    
    /**
     * Sample extension function - explores schema information
     *
     * @return true if the element defined by childName is optional in the context of the governing
     *         type of parent.
     */
    
    public static boolean isOptional(NodeInfo parent, QNameValue childName) throws Exception {
        Configuration config = parent.getConfiguration();
        SchemaType parentType = parent.getSchemaType();
        StructuredQName qn = new StructuredQName("", childName.getComponent(AccessorFn.Component.NAMESPACE).getStringValue(),
                childName.getComponent(AccessorFn.Component.LOCALNAME).getStringValue());
        int cardinality = ((ComplexType) parentType).getElementParticleCardinality(qn, true);
        return Cardinality.allowsZero(cardinality);
    }
    
    /**
     * s9api transformation pipeline
     */
    
    public void testPipeline() {
        try {
            Processor proc = new Processor(false);
            XsltCompiler comp = proc.newXsltCompiler();
    
            String xsl = "<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" +
                    "<xsl:template match='/'><a><xsl:copy-of select='.'/></a></xsl:template>" +
                    "</xsl:stylesheet>";
            String xml = "<z/>";
            XdmNode in = proc.newDocumentBuilder().build(new StreamSource(new StringReader(xml)));
            Xslt30Transformer stage1 = comp.compile(new StreamSource(new StringReader(xsl))).load30();
            Xslt30Transformer stage2 = comp.compile(new StreamSource(new StringReader(xsl))).load30();
            Xslt30Transformer stage3 = comp.compile(new StreamSource(new StringReader(xsl))).load30();
            Xslt30Transformer stage4 = comp.compile(new StreamSource(new StringReader(xsl))).load30();
            Xslt30Transformer stage5 = comp.compile(new StreamSource(new StringReader(xsl))).load30();
            XdmDestination d1 = new XdmDestination();
            stage1.applyTemplates(in, d1);
            XdmDestination d2 = new XdmDestination();
            stage2.applyTemplates(d1.getXdmNode(), d2);
            XdmDestination d3 = new XdmDestination();
            stage3.applyTemplates(d2.getXdmNode(), d3);
            XdmDestination d4 = new XdmDestination();
            stage4.applyTemplates(d3.getXdmNode(), d4);
            StringWriter sw = new StringWriter();
            Serializer out = proc.newSerializer(sw);
            stage5.applyTemplates(d4.getXdmNode(), out);
            assertTrue("output", sw.toString().contains("<a><a><a><a><a><z/></a></a></a></a></a>"));
    
        } catch (SaxonApiException err) {
            err.printStackTrace();
            fail(err.getMessage());
        }
    }
    
    /**
     * Test location information for run-time errors when stylesheet built as an XdmNode
     */
    
    public void testErrorNotificationFromSaxonParse() {
        final List<TransformerException> warnings = new ArrayList<TransformerException>(4);
        final List<TransformerException> errors = new ArrayList<TransformerException>(4);
        final List<TransformerException> fatals = new ArrayList<TransformerException>(4);
        ErrorListener listener = new ErrorListener() {
    
            public void warning(TransformerException exception) throws TransformerException {
                warnings.add(exception);
            }
    
            public void error(TransformerException exception) throws TransformerException {
                errors.add(exception);
            }
    
            public void fatalError(TransformerException exception) throws TransformerException {
                fatals.add(exception);
            }
    
        };
        try {
            // Norm Walsh reported saxon:parse errors not notified to the ErrorListener. Can't reproduce.
    
            Processor proc = new Processor(true);
            proc.getUnderlyingConfiguration().setErrorListener(listener);
    
            XsltCompiler xqcomp = proc.newXsltCompiler();
    
            StringReader sr = new StringReader("<xsl:stylesheet version='2.0' " +
                    "xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:saxon='http://saxon.sf.net/'>\n" +
                    "<xsl:template name='main'>\n" +
                    "<xsl:copy-of select=\"saxon:parse('&lt;doc>&lt;e>text&lt;/f>&lt;/doc>')\"/>\n" +
                    "</xsl:template>\n" +
                    "</xsl:stylesheet>");
    
            Xslt30Transformer trans = xqcomp.compile(new StreamSource(sr)).load30();
    
            Serializer serializer = proc.newSerializer();
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            serializer.setOutputStream(os);
    
            trans.callTemplate(new QName("main"), serializer);
    
            fail("Transformation should fail");
    
        } catch (SaxonApiException e) {
            assertTrue("warnings", warnings.isEmpty());
            assertTrue("errors", errors.isEmpty());
            assertTrue("fatals", fatals.size() == 1);
            //e.printStackTrace();
        }
    }
    
    public void testSchemaAware11() {
        // Create a Processor instance.
        try {
            Processor proc = new Processor(true);
            proc.setConfigurationProperty(FeatureKeys.TIMING, "true");
            proc.setConfigurationProperty(FeatureKeys.XSD_VERSION, "1.1");
            XsltCompiler comp = proc.newXsltCompiler();
            comp.setSchemaAware(true);
            StringReader sr = new StringReader(
                    "<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" +
                            "<xsl:import-schema><xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>" +
                            "<xs:element name='e'><xs:complexType><xs:sequence><xs:element name='p'/></xs:sequence><xs:assert test='exists(p)'/></xs:complexType></xs:element>" +
                            "</xs:schema></xsl:import-schema>" +
                            "<xsl:variable name='v'><e><p/></e></xsl:variable>" +
                            "<xsl:template name='main'><xsl:copy-of select='$v' validation='strict'/></xsl:template>" +
                            "</xsl:stylesheet>");
            XsltExecutable exec = comp.compile(new StreamSource(sr));
            Xslt30Transformer transformer = exec.load30();
    
            StringWriter sw = new StringWriter();
            Serializer serializer = proc.newSerializer(sw);
            serializer.setOutputProperty(Serializer.Property.INDENT, "no");
            transformer.callTemplate(new QName("main"), serializer);
            assertTrue(sw.toString().contains("<e>"));
        } catch (SaxonApiException e) {
            e.printStackTrace();
            fail(e.getMessage());
        }
    
    }
    
    public void testValidationWarnings() {
        try {
            Processor processor = new Processor(true);
            processor.setConfigurationProperty(FeatureKeys.VALIDATION_WARNINGS, Boolean.TRUE);
            processor.getUnderlyingConfiguration().addSchemaSource(
                new StreamSource(ConfigTest.DATA_DIR + "books.xsd"));
    
            Serializer serializer = processor.newSerializer();
            serializer.setOutputFile(new File(ConfigTest.DATA_DIR + "out/validationWarnings.xml"));
    
            XsltCompiler compiler = processor.newXsltCompiler();
            compiler.setSchemaAware(true);
    
            String xsl = "<xsl:stylesheet version=\"2.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n" +
                    "\n" +
                    "    <xsl:output indent=\"yes\" encoding=\"UTF-8\" />\n" +
                    "\n" +
                    "    <xsl:template match=\"/\">\n" +
                    "        <xsl:document validation='strict'>\n" +
                    "            <xsl:next-match />\n" +
                    "        </xsl:document>\n" +
                    "    </xsl:template>\n" +
                    "\n" +
                    "    <xsl:template match=\"*\">\n" +
                    "        <xsl:element name=\"{name()}\" namespace=\"{namespace-uri()}\">\n" +
                    "            <invalid-element/>\n" +
                    "        </xsl:element>\n" +
                    "    </xsl:template>\n" +
                    "</xsl:stylesheet> ";
            Xslt30Transformer transformer = compiler.compile(new StreamSource(new StringReader(xsl))).load30();
    
            transformer.applyTemplates(new StreamSource(new StringReader(xsl)), serializer);
        } catch (SaxonApiException e) {
            e.printStackTrace();
            fail();
        } catch (SchemaException se) {
            se.printStackTrace();
            fail();
        }
    }
    
    /**
     * Test that the base URI of the result document is the base output URI
     */
    
    public void testOutputBaseUri() throws SaxonApiException {
        try {
            Processor processor = new Processor(false);
    
            DocumentBuilder builder = processor.newDocumentBuilder();
            builder.setDTDValidation(false);
            builder.setLineNumbering(true);
    
            XdmNode document = builder.build(new File(ConfigTest.DATA_DIR + "books.xml"));
            XdmNode stylesheet = builder.build(new File(ConfigTest.DATA_DIR + "books.xsl"));
    
            XsltCompiler compiler = processor.newXsltCompiler();
            compiler.setSchemaAware(processor.isSchemaAware());
            XsltExecutable exec = compiler.compile(stylesheet.asSource());
            Xslt30Transformer transformer = exec.load30();
    
            XdmDestination result = new XdmDestination();
            transformer.setBaseOutputURI("file://tmp/out.xml");
    
            transformer.setSchemaValidationMode(ValidationMode.DEFAULT);
            transformer.setGlobalContextItem(document);
            transformer.applyTemplates(document, result);
    
            XdmNode xformed = result.getXdmNode();
            assertEquals("output base uri", "file://tmp/out.xml", xformed.getBaseURI().toString());
        } catch (SaxonApiException e) {
            System.err.println(e.getMessage());
            fail();
        }
    }
    
    /**
     * test a call on XsltExecutable.getGlobalParameters
     *
     * @throws net.sf.saxon.s9api.SaxonApiException
     *
     */
    
    public void testGlobalParameters() throws SaxonApiException, UnsupportedEncodingException {
        Configuration configuration = Configuration.newConfiguration();
        Processor processor = new Processor(configuration);
        XsltCompiler xsltCompiler = processor.newXsltCompiler();
    
        String source = "<?xml version='1.0'?>" +
                "                <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
                "                xmlns:xs='http://www.w3.org/2001/XMLSchema'" +
                "                version='2.0'>" +
    
                "                <xsl:param name='surname' as='xs:string' />" +
                "                <xsl:param name='age' as='xs:integer' />" +
    
                "                <xsl:template match='/'><xsl:element name='root' /></xsl:template>" +
                "                </xsl:stylesheet>";
    
        XsltExecutable xsltExecutable = xsltCompiler.compile(new StreamSource(new ByteArrayInputStream(source.getBytes("UTF-8"))));
        Map<QName, XsltExecutable.ParameterDetails> params = xsltExecutable.getGlobalParameters();
    
        System.out.println();
        int i = 0;
        for (QName key : params.keySet()) {
            System.out.println("Parameter n." + (++i) + ": " + key);
        }
        System.out.println();
        assertEquals(2, 2);
    }
    
    /**
     * Test an external  call on a stylesheet function
     *
     * @throws net.sf.saxon.s9api.SaxonApiException
     *          if the call fails
     */
    
    public void testCallFunction() throws SaxonApiException {
        try {
            Configuration configuration = Configuration.newConfiguration();
            Processor processor = new Processor(configuration);
            XsltCompiler xsltCompiler = processor.newXsltCompiler();
    
            String source = "<?xml version='1.0'?>" +
                    "                <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
                    "                xmlns:xs='http://www.w3.org/2001/XMLSchema'" +
                    "                xmlns:f='http://localhost/'" +
                    "                version='2.0'>" +
                    "                <xsl:function name='f:add'><xsl:param name='a'/><xsl:param name='b'/>" +
                    "                  <xsl:sequence select='$a + $b'/></xsl:function>" +
                    "                </xsl:stylesheet>";
    
            StreamSource ss = new StreamSource(new ByteArrayInputStream(source.getBytes("UTF-8")), "file:///dummy/");
            XsltExecutable xsltExecutable = xsltCompiler.compile(ss);
            Xslt30Transformer t = xsltExecutable.load30();
            XdmValue v = t.callFunction(new QName("http://localhost/", "f:add"), new XdmValue[]{new XdmAtomicValue(2), new XdmAtomicValue(3)});
            assertEquals(((XdmAtomicValue) v).getLongValue(), 5);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            fail();
        }
    }
    
    /**
     * Test an external  call on a stylesheet function with argument conversion
     *
     * @throws net.sf.saxon.s9api.SaxonApiException
     *          if the call fails
     */
    
    public void testCallFunctionArgConversion() throws SaxonApiException {
        try {
            Configuration configuration = Configuration.newConfiguration();
            Processor processor = new Processor(configuration);
            XsltCompiler xsltCompiler = processor.newXsltCompiler();
    
            String source = "<?xml version='1.0'?>" +
                    "                <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
                    "                xmlns:xs='http://www.w3.org/2001/XMLSchema'" +
                    "                xmlns:f='http://localhost/'" +
                    "                version='2.0'>" +
                    "                <xsl:function name='f:add'>" +
                    "                   <xsl:param name='a' as='xs:double'/>" +
                    "                   <xsl:param name='b' as='xs:double'/>" +
                    "                   <xsl:sequence select='$a + $b'/>" +
                    "                </xsl:function>" +
                    "                </xsl:stylesheet>";
    
            StreamSource ss = new StreamSource(new ByteArrayInputStream(source.getBytes("UTF-8")), "file:///dummy/");
            XsltExecutable xsltExecutable = xsltCompiler.compile(ss);
            Xslt30Transformer t = xsltExecutable.load30();
            XdmValue v = t.callFunction(new QName("http://localhost/", "f:add"), new XdmValue[]{new XdmAtomicValue(2), new XdmAtomicValue(3)});
            assertEquals(((XdmAtomicValue) v).getDoubleValue(), 5.0e0);
            assertEquals((((XdmAtomicValue) v)).getPrimitiveTypeName().getLocalName(), "double");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            fail();
        }
    }
    
    /**
     * Test an external  call on a stylesheet function serializing the results
     * Also makes access to a stylesheet parameter which in turn accesses the global context item
     *
     * @throws net.sf.saxon.s9api.SaxonApiException
     *          if the call fails
     */
    
    public void testCallFunctionWrapResults() throws SaxonApiException {
        try {
            Processor processor = new Processor(true);
            processor.setConfigurationProperty(FeatureKeys.GENERATE_BYTE_CODE, "false");
            XsltCompiler xsltCompiler = processor.newXsltCompiler();
    
            String source = "<?xml version='1.0'?>" +
                    "                <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
                    "                xmlns:xs='http://www.w3.org/2001/XMLSchema'" +
                    "                xmlns:f='http://localhost/'" +
                    "                version='2.0'>" +
                    "                <xsl:param name='x' as='xs:integer'/>" +
                    "                <xsl:param name='y' select='.+2'/>" +
                    "                <xsl:function name='f:add'>" +
                    "                   <xsl:param name='a' as='xs:double'/>" +
                    "                   <xsl:param name='b' as='xs:double'/>" +
                    "                   <xsl:sequence select='$a + $b + $x + $y'/>" +
                    "                </xsl:function>" +
                    "                </xsl:stylesheet>";
    
            StreamSource ss = new StreamSource(new ByteArrayInputStream(source.getBytes("UTF-8")), "file:///dummy/");
            XsltExecutable xsltExecutable = xsltCompiler.compile(ss);
            Xslt30Transformer t = xsltExecutable.load30();
            t.setGlobalContextItem(new XdmAtomicValue(20));
            Map<QName, XdmValue> globals = new HashMap<QName, XdmValue>();
            globals.put(new QName("x"), new XdmAtomicValue(30));
            t.setStylesheetParameters(globals);
            StringWriter sw = new StringWriter();
            Serializer s = processor.newSerializer();
            s.setOutputProperty(Serializer.Property.OMIT_XML_DECLARATION, "yes");
            s.setOutputWriter(sw);
            t.callFunction(new QName("http://localhost/", "f:add"), new XdmValue[]{new XdmAtomicValue(2), new XdmAtomicValue(3)}, s);
            assertEquals(sw.toString(), "57");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            fail();
        }
    }
    
    /**
     * Test an external  call on a stylesheet function with invalid argument conversion
     *
     * @throws net.sf.saxon.s9api.SaxonApiException
     *          if the call fails
     */
    
    public void testCallFunctionArgInvalid() throws SaxonApiException {
        try {
            Configuration configuration = Configuration.newConfiguration();
            Processor processor = new Processor(configuration);
            XsltCompiler xsltCompiler = processor.newXsltCompiler();
    
            String source = "<?xml version='1.0'?>" +
                    "                <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
                    "                xmlns:xs='http://www.w3.org/2001/XMLSchema'" +
                    "                xmlns:f='http://localhost/'" +
                    "                version='2.0'>" +
                    "                <xsl:function name='f:add'>" +
                    "                   <xsl:param name='a' as='xs:double'/>" +
                    "                   <xsl:param name='b' as='xs:double'/>" +
                    "                   <xsl:sequence select='$a + $b'/>" +
                    "                </xsl:function>" +
                    "                </xsl:stylesheet>";
    
            StreamSource ss = new StreamSource(new ByteArrayInputStream(source.getBytes("UTF-8")), "file:///dummy/");
            XsltExecutable xsltExecutable = xsltCompiler.compile(ss);
            Xslt30Transformer t = xsltExecutable.load30();
            XdmValue v = t.callFunction(new QName("http://localhost/", "f:add"), new XdmValue[]{new XdmAtomicValue(2), new XdmAtomicValue("3")});
            fail("Failed to throw error");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            fail();
        } catch (SaxonApiException e) {
            System.err.println(e.getMessage());
            // OK
        }
    }
    
    /**
     * Test calling a stylesheet with an initial template with parameters
     *
     * @throws net.sf.saxon.s9api.SaxonApiException
     *          if the call fails
     */
    
    public void testCallNamedTemplateWithParams() throws SaxonApiException {
        try {
            Configuration configuration = Configuration.newConfiguration();
            //configuration.setConfigurationProperty(FeatureKeys.GENERATE_BYTE_CODE, false);
            Processor processor = new Processor(configuration);
            XsltCompiler xsltCompiler = processor.newXsltCompiler();
    
            String source = "<?xml version='1.0'?>" +
                    "                <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
                    "                xmlns:xs='http://www.w3.org/2001/XMLSchema'" +
                    "                version='3.0'>" +
                    "                <xsl:template name='t'>" +
                    "                   <xsl:param name='a' as='xs:double'/>" +
                    "                   <xsl:param name='b' as='xs:float'/>" +
                    "                   <xsl:sequence select='$a + $b'/>" +
                    "                </xsl:template>" +
                    "                </xsl:stylesheet>";
    
            StreamSource ss = new StreamSource(new ByteArrayInputStream(source.getBytes("UTF-8")), "file:///dummy/");
            XsltExecutable xsltExecutable = xsltCompiler.compile(ss);
            Xslt30Transformer t = xsltExecutable.load30();
            Map<QName, XdmValue> params = new HashMap<QName, XdmValue>();
            params.put(new QName("a"), new XdmAtomicValue(12));
            params.put(new QName("b"), new XdmAtomicValue(5));
            t.setInitialTemplateParameters(params, false);
            StringWriter sw = new StringWriter();
            Serializer se = processor.newSerializer(sw);
            se.setOutputProperty(Serializer.Property.OMIT_XML_DECLARATION, "yes");
            t.callTemplate(new QName("t"), se);
            assertEquals(sw.toString(), "17");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            fail();
        }
    }
    
    /**
     * Test calling a stylesheet with an initial template omitting a required parameters
     *
     * @throws net.sf.saxon.s9api.SaxonApiException
     *          if the call fails
     */
    
    public void testCallNamedTemplateWithParamsRequired() throws SaxonApiException {
        try {
            Configuration configuration = Configuration.newConfiguration();
            //configuration.setConfigurationProperty(FeatureKeys.GENERATE_BYTE_CODE, false);
            Processor processor = new Processor(configuration);
            XsltCompiler xsltCompiler = processor.newXsltCompiler();
    
            String source = "<?xml version='1.0'?>" +
                    "                <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
                    "                xmlns:xs='http://www.w3.org/2001/XMLSchema'" +
                    "                version='3.0'>" +
                    "                <xsl:template name='t'>" +
                    "                   <xsl:param name='a' as='xs:double'/>" +
                    "                   <xsl:param name='b' as='xs:float' required='yes'/>" +
                    "                   <xsl:sequence select='$a + $b'/>" +
                    "                </xsl:template>" +
                    "                </xsl:stylesheet>";
    
            StreamSource ss = new StreamSource(new ByteArrayInputStream(source.getBytes("UTF-8")), "file:///dummy/");
            XsltExecutable xsltExecutable = xsltCompiler.compile(ss);
            Xslt30Transformer t = xsltExecutable.load30();
            Map<QName, XdmValue> params = new HashMap<QName, XdmValue>();
            params.put(new QName("a"), new XdmAtomicValue(12));
            t.setInitialTemplateParameters(params, false);
            StringWriter sw = new StringWriter();
            Serializer se = processor.newSerializer(sw);
            se.setOutputProperty(Serializer.Property.OMIT_XML_DECLARATION, "yes");
            t.callTemplate(new QName("t"), se);
            fail("failed to detect error");
        } catch (SaxonApiException e) {
            assertTrue("message", e.getMessage().contains("required parameter $b"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            fail();
        }
    }
    
    /**
     * Test calling a stylesheet with an initial template with tunnel parameters
     *
     * @throws net.sf.saxon.s9api.SaxonApiException
     *          if the call fails
     */
    
    public void testCallNamedTemplateWithTunnelParams() throws SaxonApiException {
        try {
            Configuration configuration = Configuration.newConfiguration();
            //configuration.setConfigurationProperty(FeatureKeys.GENERATE_BYTE_CODE, false);
            Processor processor = new Processor(configuration);
            XsltCompiler xsltCompiler = processor.newXsltCompiler();
    
            String source = "<?xml version='1.0'?>" +
                    "                <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
                    "                xmlns:xs='http://www.w3.org/2001/XMLSchema'" +
                    "                version='3.0'>" +
                    "                <xsl:template name='t'>" +
                    "                   <xsl:call-template name='u'/>" +
                    "                </xsl:template>" +
                    "                <xsl:template name='u'>" +
                    "                   <xsl:param name='a' as='xs:double' tunnel='yes'/>" +
                    "                   <xsl:param name='b' as='xs:float' tunnel='yes'/>" +
                    "                   <xsl:sequence select='$a + $b'/>" +
                    "                </xsl:template>" +
                    "                </xsl:stylesheet>";
    
            StreamSource ss = new StreamSource(new ByteArrayInputStream(source.getBytes("UTF-8")), "file:///dummy/");
            XsltExecutable xsltExecutable = xsltCompiler.compile(ss);
            Xslt30Transformer t = xsltExecutable.load30();
            Map<QName, XdmValue> params = new HashMap<QName, XdmValue>();
            params.put(new QName("a"), new XdmAtomicValue(12));
            params.put(new QName("b"), new XdmAtomicValue(5));
            t.setInitialTemplateParameters(params, true);
            StringWriter sw = new StringWriter();
            Serializer se = processor.newSerializer(sw);
            se.setOutputProperty(Serializer.Property.OMIT_XML_DECLARATION, "yes");
            t.callTemplate(new QName("t"), se);
            assertEquals(sw.toString(), "17");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            fail();
        }
    }
    
    /**
     * Test calling a stylesheet with an initial template rule with parameters
     *
     * @throws net.sf.saxon.s9api.SaxonApiException
     *          if the call fails
     */
    
    public void testCallTemplateRuleWithParams() throws SaxonApiException {
        try {
            Configuration configuration = Configuration.newConfiguration();
            //configuration.setConfigurationProperty(FeatureKeys.GENERATE_BYTE_CODE, false);
            Processor processor = new Processor(configuration);
            XsltCompiler xsltCompiler = processor.newXsltCompiler();
    
            String source = "<?xml version='1.0'?>" +
                    "                <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
                    "                xmlns:xs='http://www.w3.org/2001/XMLSchema'" +
                    "                version='3.0'>" +
                    "                <xsl:template match='*'>" +
                    "                   <xsl:param name='a' as='xs:double'/>" +
                    "                   <xsl:param name='b' as='xs:float'/>" +
                    "                   <xsl:sequence select='name(.), $a + $b'/>" +
                    "                </xsl:template>" +
                    "                </xsl:stylesheet>";
    
            StreamSource ss = new StreamSource(new ByteArrayInputStream(source.getBytes("UTF-8")), "file:///dummy/");
            XsltExecutable xsltExecutable = xsltCompiler.compile(ss);
            Xslt30Transformer t = xsltExecutable.load30();
            Map<QName, XdmValue> params = new HashMap<QName, XdmValue>();
            params.put(new QName("a"), new XdmAtomicValue(12));
            params.put(new QName("b"), new XdmAtomicValue(5));
            t.setInitialTemplateParameters(params, false);
            StringWriter sw = new StringWriter();
            Serializer se = processor.newSerializer(sw);
            se.setOutputProperty(Serializer.Property.OMIT_XML_DECLARATION, "yes");
            t.applyTemplates(new StreamSource(new StringReader("<e/>")), se);
            assertEquals(sw.toString(), "e 17");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            fail();
        }
    }
    
    /**
     * Test calling a stylesheet named template getting raw results back
     *
     * @throws net.sf.saxon.s9api.SaxonApiException if the call fails
     */
    
    public void testCallNamedTemplateWithParamsRaw() throws SaxonApiException {
        try {
            Configuration configuration = Configuration.newConfiguration();
            //configuration.setConfigurationProperty(FeatureKeys.GENERATE_BYTE_CODE, false);
            Processor processor = new Processor(configuration);
            XsltCompiler xsltCompiler = processor.newXsltCompiler();
    
            String source = "<?xml version='1.0'?>" +
                "                <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
                "                xmlns:xs='http://www.w3.org/2001/XMLSchema'" +
                "                version='3.0'>" +
                "                <xsl:template name='t'>" +
                "                   <xsl:param name='a' as='xs:double'/>" +
                "                   <xsl:param name='b' as='xs:float'/>" +
                "                   <xsl:sequence select='$a+1, $b+1'/>" +
                "                </xsl:template>" +
                "                </xsl:stylesheet>";
    
            StreamSource ss = new StreamSource(new ByteArrayInputStream(source.getBytes("UTF-8")), "file:///dummy/");
            XsltExecutable xsltExecutable = xsltCompiler.compile(ss);
            Xslt30Transformer t = xsltExecutable.load30();
            Map<QName, XdmValue> params = new HashMap<QName, XdmValue>();
            params.put(new QName("a"), new XdmAtomicValue(12));
            params.put(new QName("b"), new XdmAtomicValue(5));
            t.setInitialTemplateParameters(params, false);
            XdmValue val = t.callTemplate(new QName("t"));
            assertEquals(2, val.size());
            assertEquals(13, ((XdmAtomicValue) val.itemAt(0)).getLongValue());
            assertEquals(6, ((XdmAtomicValue) val.itemAt(1)).getLongValue());
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            fail();
        }
    }
    
    /**
     * Test calling a stylesheet with an initial template rule getting the raw result
     *
     * @throws net.sf.saxon.s9api.SaxonApiException if the call fails
     */
    
    public void testApplyTemplatesRaw() throws SaxonApiException {
        try {
            Configuration configuration = Configuration.newConfiguration();
            Processor processor = new Processor(configuration);
            XsltCompiler xsltCompiler = processor.newXsltCompiler();
    
            String source = "<?xml version='1.0'?>" +
                "                <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" +
                "                xmlns:xs='http://www.w3.org/2001/XMLSchema'" +
                "                version='3.0'>" +
                "                <xsl:template match='*'>" +
                "                   <xsl:param name='a' as='xs:double'/>" +
                "                   <xsl:param name='b' as='xs:float'/>" +
                "                   <xsl:sequence select='., $a + $b'/>" +
                "                </xsl:template>" +
                "                </xsl:stylesheet>";
    
            StreamSource ss = new StreamSource(new ByteArrayInputStream(source.getBytes("UTF-8")), "file:///dummy/");
            XsltExecutable xsltExecutable = xsltCompiler.compile(ss);
            Xslt30Transformer t = xsltExecutable.load30();
            Map<QName, XdmValue> params = new HashMap<QName, XdmValue>();
            params.put(new QName("a"), new XdmAtomicValue(12));
            params.put(new QName("b"), new XdmAtomicValue(5));
            t.setInitialTemplateParameters(params, false);
            StringWriter sw = new StringWriter();
            Serializer se = processor.newSerializer(sw);
            se.setOutputProperty(Serializer.Property.OMIT_XML_DECLARATION, "yes");
            XdmValue result = t.applyTemplates(new StreamSource(new StringReader("<e/>")));
            assertEquals("size", 2, result.size());
            XdmItem first = result.itemAt(0);
            assertTrue("t1", first instanceof XdmNode);
            assertEquals("v1", ((XdmNode) first).getNodeName().getLocalName(), "e");
            XdmItem second = result.itemAt(1);
            assertTrue("t2", second instanceof XdmAtomicValue);
            assertEquals("v2", ((XdmAtomicValue) second).getDoubleValue(), 17e0);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            fail();
        }
    }
    
    /**
     * Test Strip-type-annotations with ApplyTemplates
     */
    
    public void testStripTypeAnnotations() {
        try {
            Processor proc = new Processor(true);
            XsltCompiler comp = proc.newXsltCompiler();
            StringReader sr = new StringReader("<xslt:transform xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n" +
                    "                xmlns:my=\"http://ns.example.com/strip-type\"\n" +
                    "                xmlns:xslt=\"http://www.w3.org/1999/XSL/Transform\"\n" +
                    "                exclude-result-prefixes=\"xs my\"\n" +
                    "                input-type-annotations=\"strip\"\n" +
                    "                version=\"2.0\">\n" +
                    "<!-- Purpose: Show that when @input-type-annotations=\"strip\", is-nilled property of element  nodes is set to false.-->\n" +
                    "\n" +
                    "   <xslt:template match=\"/my:userNode\">\n" +
                    "      <out>\n" +
                    "         <xslt:value-of select=\"nilled(.)\"/>\n" +
                    "      </out>\n" +
                    "   </xslt:template>\n" +
                    "</xslt:transform>");
    
            SchemaManager manager = proc.getSchemaManager();
            comp.setSchemaAware(true);
    
            manager.load(new StreamSource(new File(ConfigTest.DATA_DIR + "varietyOfTypes.xsd")));
    
            XsltExecutable exec = comp.compile(new StreamSource(sr));
            Xslt30Transformer xsl = exec.load30();
            String in = "<?xml version='1.0'?> \n" +
                    "<my:userNode xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
                    "\t\t  xsi:schemaLocation=\"http://ns.example.com/strip-type varietyOfTypes.xsd\"\n" +
                    "\t\t  xmlns:my=\"http://ns.example.com/strip-type\"\n" +
                    "\t \t  specialPart=\"123-AB\" listParts=\"000-SS 000-RR\" xsi:nil=\"true\"/>";
    
            SchemaValidator validator = manager.newSchemaValidator();
            validator.setLax(false);
            DocumentBuilder builder = proc.newDocumentBuilder();
            builder.setSchemaValidator(validator);
            StreamSource sDoc = new StreamSource(new ByteArrayInputStream(in.getBytes("UTF-8")), "file:///dummy/");
            XdmNode doc = builder.build(sDoc);
    
            StringWriter writer = new StringWriter();
            Serializer out = proc.newSerializer(writer);
            xsl.applyTemplates(doc, out);
            assertTrue("strip-type-annotations not working", writer.toString().contains("false"));
        } catch (Exception e) {
            e.printStackTrace();
            fail(e.getMessage());
        }
    
    }
    

    }

     
    • Anonymous

      Anonymous - 2015-10-15

      Thanks a lot Michael. Much appreciated.
      Can I ask you one more question. Is it possible to provide more than one XML files and getting it transformed with single XSL file?
      If yes how to do that?

      Also is XsltTransformer.Run() similar to Xslt30Transformer.applyTemplates() method.

      Thanks for all your help in advance.

      Regards

       
    • Michael Kay

      Michael Kay - 2015-10-15

      There are many ways you can process multiple documents in a single transformation. You can read them using the collection() function, perhaps with your own CollectionURIResolver; you can read them individually using the doc() or document() functions; you can pass them as stylesheet parameters. In XSLT 3.0 (and with the Xslt30Transformer) you can even pass a sequence of documents (as an XdmValue) to the method applyTemplates (XdmValue, Destination) - though this isn't as useful as it appears because you can then only process the documents individually and independently, you can't combine them in any way.

       

Anonymous
Anonymous

Add attachments
Cancel