XML transformation with DOMResult
Solution 1
DOMResult output = new DOMResult();
TransformerFactory.newInstance().
newTransformer(new StreamSource(xsl)).
transform(input, output);
return (Document) output.getNode();
Reference:
DOMResult#getNode()
Get the node that will contain the result DOM tree. If no node was set via DOMResult(Node node), ... , then the node will be set by the transformation, and may be obtained from this method once the transformation is complete.
Solution 2
I suspect the output of the transformation is not well-formed XML
. I can get the same exception with the following code and input files.
XmlTransform.java
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;
import java.io.*;
import org.w3c.dom.*;
public class XmlTransform {
public static void main(String[] args) throws Exception {
File xsl = new File("1.xsl");
File xml = new File("1.xml");
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = db.newDocument();
DOMSource input = new DOMSource(db.parse(xml));
// StreamResult output = new StreamResult(System.out); //That works but its not what I want!
DOMResult output = new DOMResult(document); //that gives the null pointer exception
TransformerFactory.newInstance().newTransformer(new StreamSource(xsl)).transform(input, output);
System.out.println("getNode().getLocalName()=" + output.getNode().getLocalName());
System.out.println("((Document)getNode()).getDocumentElement().getLocalName()=" + ((Document)output.getNode()).getDocumentElement().getLocalName());
Node n = ((Document)output.getNode()).getDocumentElement();
System.out.println("n.hasChildNodes()=" + n.hasChildNodes());
System.out.println("Beatles=" + n.getChildNodes().getLength());
}
}
1.xml
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="//beatle" />
</xsl:template>
<xsl:template match="beatle">
<xsl:value-of select="name/first"/>
</xsl:template>
</xsl:stylesheet>
1.xsl
<?xml version="1.0" encoding="UTF-8"?>
<beatles>
<beatle>
<name>
<first>John</first>
<last>Lennon</last>
</name>
</beatle>
<beatle>
<name>
<first>Paul</first>
<last>McCartney</last>
</name>
</beatle>
<beatle>
<name>
<first>George</first>
<last>Harrison</last>
</name>
</beatle>
<beatle>
<name>
<first>Ringo</first>
<last>Starr</last>
</name>
</beatle>
</beatles>
Compiling and running this, I get the following exception:
getNode().getLocalName()=null
Exception in thread "main" java.lang.NullPointerException
at XmlTransform.main(XmlTransform.java:27)
which isn't exactly the same as yours (see later!) but replacing the output System.out, I get
JohnPaulGeorgeRingo
as expected.
Now, the output isn't exactly XML
so if you start to add elements to the XSLT
, for example, lets wrap each name with a <name></name>
with:
<name><xsl:value-of select="name/first"/></name>
and switch back to the DOMResult output
this results in a different exception:
ERROR: 'HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted. '
Exception in thread "main" javax.xml.transform.TransformerException: org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:736)
because the output is not a well-formed XML
document. There must be only one root node in an XML document. So by replacing:
<xsl:apply-templates select="//beatle" />
with:
<names><xsl:apply-templates select="//beatle" /></names>
makes the output document well-formed and the terminal result should be:
getNode().getLocalName()=null
((Document)getNode()).getDocumentElement().getLocalName()=names
n.hasChildNodes()=true
Beatles=4
Hope this helps.
Related videos on Youtube
Admin
Updated on September 14, 2022Comments
-
Admin over 1 year
I'm getting
java.lang.NullPointerException
when I uncomment a line in the following code:private static Document XSLT(String name) throws Exception{ File xsl = new File("data/" + name + ".xsl"); File xml = new File("data/" + name + ".xml"); DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document document = db.newDocument(); DOMSource input = new DOMSource(db.parse(xml)); StreamResult output = new StreamResult(System.out); //That works but its not what I want! //DOMResult output = new DOMResult(document); //that gives the null pointer exception TransformerFactory.newInstance().newTransformer(new StreamSource(xsl)).transform(input, output); return document; }
My intention is to make a method like that to help me transform a XML file, using both XSLT and Java language. After all I should do all the transformations before saving it into a file.
How to get a Document out of that method?
I mean, I want to do this without saving the transformed document into a file to be able to load it, I want to do it just in the "memory".
Thank you :)
Update
Let me publish the exception so you can help me better.
Exception in thread "main" javax.xml.transform.TransformerException: java.lang.NullPointerException at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:736) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:340) at test.Main.XSLT(Main.java:393) at test.Main.test(Main.java:342) at test.Main.main(Main.java:329) Caused by: java.lang.NullPointerException at com.sun.org.apache.xml.internal.serializer.SerializerBase.patchName(SerializerBase.java:271) at com.sun.org.apache.xml.internal.serializer.SerializerBase.addAttribute(SerializerBase.java:429) at com.sun.org.apache.xml.internal.serializer.ToSAXHandler.addUniqueAttribute(ToSAXHandler.java:438) at xmlname.template$dot$0() at xmlname.applyTemplates() at xmlname.transform() at com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet.transform(AbstractTranslet.java:611) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:729) ... 4 more --------- java.lang.NullPointerException at com.sun.org.apache.xml.internal.serializer.SerializerBase.patchName(SerializerBase.java:271) at com.sun.org.apache.xml.internal.serializer.SerializerBase.addAttribute(SerializerBase.java:429) at com.sun.org.apache.xml.internal.serializer.ToSAXHandler.addUniqueAttribute(ToSAXHandler.java:438) at xmlname.template$dot$0() at xmlname.applyTemplates() at xmlname.transform() at com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet.transform(AbstractTranslet.java:611) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:729) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:340) at test.Main.XSLT(Main.java:393) at test.Main.test(Main.java:342) at test.Main.main(Main.java:329)
Update 2
Lets test with a common source.
test.xml
<?xml version="1.0" encoding="UTF-8"?> <tests> <test> <text>Hi!</text> </test> </tests>
test.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" version="1.0" encoding="utf-8" indent="yes" omit-xml-declaration="no" media-type="application/xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" /> <xsl:template match="/"> <html xmlns="http://www.w3.org/1999/xhtml" lang="pt-BR" xml:lang="pt-BR"> <head> <meta charset="UTF-8" /> <title>Test</title> </head> <body> <h1>Test</h1> <xsl:apply-templates/> </body> </html> </xsl:template> <xsl:template match="/tests/test"> <p><xsl:value-of select="text"/></p> </xsl:template> </xsl:stylesheet>
Gives the following output using
StreamResult
.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="pt-BR" xml:lang="pt-BR" xmlns="http://www.w3.org/1999/xhtml"> <head> <META http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta charset="UTF-8"> <title>Test</title> </head> <body> <h1>Test</h1> <p>Hi!</p> </body> </html>
Solved
See my answer in the appropriate place (in the answers!)