igarashitm.log

igarashitm, a Japanese software engineer writes something in English here.

XSLT transformation using DOMSource & DOMResult

Just reminder. really hit a wall.

The points are following two. It's no problem if the source is always String, but sometimes not somehow.

  1. need to do DocumentBuilderFactory#setNamespaceAware(true) when creating DOMSource from String, or XSLT transformation fails afterward. And what is worse, it doesn't return a error but empty result.
  2. DOMResult#getNode() actually returns Document, so need to do like this - ((Document)domresult.getNode()).getDocumentElement() - I don't like this. use getDocument() as method name if it returns the Document.

XsltTransformTest.java - Testcase using StreamSource, StreamResult as well

import java.io.StringReader;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.w3c.dom.Document;
import org.xml.sax.InputSource;

public class XsltTransformTest {
    private static final String XML =
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                    "<orders:order xmlns:orders=\"urn:switchyard-quickstart:transform-xslt:1.0\">\n" +
                    "    <orderId>PO-19838-XYZ</orderId>\n" +
                    "    <itemId>BUTTER</itemId>\n" +
                    "    <quantity>200</quantity>\n" +
                    "</orders:order>";
    
    private static final String XSLT =
            "<?xml version=\"1.0\"?>\n"
            + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
            + "    <xsl:template match=\"/\">\n"
            + "        <orders:orderAck xmlns:orders=\"urn:switchyard-quickstart:transform-xslt:1.0\">\n"
            + "            <xsl:for-each select=\"orders:order\">\n"
            + "                <orderId>\n"
            + "                    <xsl:value-of select=\"orderId\" />\n"
            + "                </orderId>\n"
            + "                <accepted>\n"
            + "                    <xsl:choose>\n"
            + "                        <xsl:when test=\"(itemId = 'BUTTER') and (quantity &lt;= 200)\">\n"
            + "                            true\n"
            + "                        </xsl:when>\n"
            + "                        <xsl:otherwise>\n"
            + "                            false\n"
            + "                        </xsl:otherwise>\n"
            + "                    </xsl:choose>\n"
            + "                </accepted>\n"
            + "                <status>\n"
            + "                    <xsl:choose>\n"
            + "                        <xsl:when test=\"(itemId = 'BUTTER') and (quantity &lt;= 200)\">\n"
            + "                            Order Accepted\n"
            + "                        </xsl:when>\n"
            + "                        <xsl:when test=\"itemId != 'BUTTER'\">\n"
            + "                            No Such Item:\n"
            + "                            <xsl:value-of select=\"itemId\" />\n"
            + "                        </xsl:when>\n"
            + "                        <xsl:when test=\"quantity &gt; 200\">\n"
            + "                            Not Enough Stock\n"
            + "                        </xsl:when>\n"
            + "                        <xsl:otherwise>\n"
            + "                            UNKNOWN\n"
            + "                        </xsl:otherwise>\n"
            + "                    </xsl:choose>\n"
            + "                </status>\n"
            + "            </xsl:for-each>\n"
            + "        </orders:orderAck>\n"
            + "    </xsl:template>\n"
            + "</xsl:stylesheet>";
    
    public static void main(String[] args) throws Exception {
        new XsltTransformTest().perform();
    }
    
    public void perform() throws Exception {
        System.out.println("* * *  StreamSource => StreamResult  * * *");
        transform(XSLT, createStreamSource(XML), new StreamResult(System.out));
        System.out.println("\n* * *  DOMSource => StreamResult  * * *");
        transform(XSLT, createDOMSource(XML), new StreamResult(System.out));

        DOMResult result = new DOMResult();
        System.out.println("\n* * *  StreamSource => DOMResult  * * *");
        printDOMResult(transform(XSLT, createStreamSource(XML), result));
        result = new DOMResult();
        System.out.println("\n* * *  DOMSource => DOMResult  * * *");
        printDOMResult(transform(XSLT, createDOMSource(XML), result));
    }
    
    private void printDOMResult(DOMResult dom) throws Exception {
        System.out.println("getNode().getLocalName()="
                + dom.getNode().getLocalName()
                + ", ((Document)getNode()).getDocumentElement().getLocalName()="
                + ((Document)dom.getNode()).getDocumentElement().getLocalName());
    }

    private <T extends Result> T transform(String xslt, Source source, T result) throws Exception {
        javax.xml.transform.TransformerFactory tFactory = javax.xml.transform.TransformerFactory.newInstance();
        Templates templates = tFactory.newTemplates(new StreamSource(new StringReader(xslt)));
        javax.xml.transform.Transformer transformer = templates.newTransformer();
        transformer.transform(source, result);
        return result;
    }
    
    private DOMSource createDOMSource(String str) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        InputSource input = new InputSource(new StringReader(str));
        Document document = factory.newDocumentBuilder().parse(input);
        return new DOMSource(document.getDocumentElement());
    }
    
    private StreamSource createStreamSource(String str) throws Exception {
        return new StreamSource(new StringReader(str));
    }
}

output

* * *  StreamSource => StreamResult  * * *
<?xml version="1.0" encoding="UTF-8"?><orders:orderAck xmlns:orders="urn:switchyard-quickstart:transform-xslt:1.0"><orderId>PO-19838-XYZ</orderId><accepted>
                            true
                        </accepted><status>
                            Order Accepted
                        </status></orders:orderAck>
* * *  DOMSource => StreamResult  * * *
<?xml version="1.0" encoding="UTF-8"?><orders:orderAck xmlns:orders="urn:switchyard-quickstart:transform-xslt:1.0"><orderId>PO-19838-XYZ</orderId><accepted>
                            true
                        </accepted><status>
                            Order Accepted
                        </status></orders:orderAck>
* * *  StreamSource => DOMResult  * * *
getNode().getLocalName()=null, ((Document)getNode()).getDocumentElement().getLocalName()=orderAck

* * *  DOMSource => DOMResult  * * *
getNode().getLocalName()=null, ((Document)getNode()).getDocumentElement().getLocalName()=orderAck