Reputation:
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 :)
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)
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>
See my answer in the appropriate place (in the answers!)
Upvotes: 4
Views: 11965
Reputation:
The XHTML inside the XSL file was right (XML compliant), but the output after the XSLT processing was not.
I looked the line (in the output of the XSLT proc):
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
The meta
was all uppercase, and the >
should be />
.
So I changed the line where we see the method
from html
:
<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"
/>
To xml
:
<xsl:output
method="xml"
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"
/>
I was having problems with self-closing tags, then I had to change another thing for the output be real XHTML compliant for the browsers.
Changing the following line fix these issues:
media-type="application/xhtml+xml"
So an empty div:
<div/>
Will be written as:
<div></div>
I tested it with the XSLT processor that came with the default JDK and it works.
Upvotes: 1
Reputation: 43823
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.
Upvotes: 1
Reputation: 51721
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.
Upvotes: 5