How do you debug an xml object that causes a transform error when writing to string?
Solution 1
I am guessing that the error is with one of your objects, either because that object is not valid XML or because the XML has an empty (null) text node rather than an empty string value.
see java.lang.NullPointerException
at com.sun.org.apache.xml.internal.serializer. ToUnknownStream.characters(ToUnknownStream.java:338)
Based on the link in @Sajan Chandran's comment:
If you take a look at that you will see the code.
public void characters(String chars) throws SAXException
{
final int length = chars.length();
The issue being char.length()
is zero because of a null text node.
As it states, to fix this simply make sure all XML nodes have a string value rather than 'null' value.
If this does not work can you post an example of the XML object that causes the exception to be thrown. Also, can you check that the object is valid XML and that character entities, etc, are properly encoded.
Solution 2
Basically agreeing with the other answers, except:
The problem would be that you have a text node with null (not empty) character content, in your doc
or e
data structure.
While Kiran's post (linked by Sajan) is helpful, I'm pretty sure he's mistaken about "the chars.length() was zero because there was a null text node insertion being tried." The chars.length()
was not zero; the call to chars.length()
threw an NPE because chars
was null.
To find the problem, add a method call here:
if (e != null) {
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
source = new DOMSource(e);
checkForNullTextNodes(e); // ADDED
} else {
source = new DOMSource(doc);
checkForNullTextNodes(doc); // ADDED
}
transformer.transform(source, result); // <-- Error occurs here
Then define checkForNullTextNodes(node)
to: (pseudocode)
- walk through the tree with
n
for each node - check each text node for null character data
E.g. (still semi-pseudocode)
if (n.getType() == org.w3c.dom.Node.TEXT_NODE && n.getNodeValue() == null) {
throw new Exception("Text node with null content: " +
path to this node);
}
That should help you find out where any text nodes with null character content are, which should help you figure out where they are coming from. Where are these doc
or e
structures being created, anyway?
Solution 3
I agree with the other answer, here is the code I used to get rid of the null
nodes
public void deleteNullNode(Node racine)
{
NodeList nl = racine.getChildNodes();
for (int i = 0; i < nl.getLength(); i++)
{
if (nl.item(i).getNodeType() == Node.TEXT_NODE && nl.item(i).getNodeValue() == null)
{
nl.item(i).getParentNode().removeChild(nl.item(i));
}
else
{
deleteNullNode(nl.item(i));
}
}
}
vextorspace
I am the Lead Developer at Protocase Inc. We are a mass customization sheet metal enclosures company - another words if you want a sheet metal enclosure for a project and it needs to be professional quality, we will do it in a few days for not much money, even if you want only 1. I took this job for two reasons: it was interesting and it is not in a giant metropolis. It is in Cape Breton, recently voted #1 island destination in north america. I love hiking, biking, snowboarding, cross country skiing, and sailing. I can do all those in a small area here! In case you were wondering, we currently need more programmers! Send me a resume if you are interested.
Updated on April 20, 2021Comments
-
vextorspace about 3 years
I have an XML Object and when I transform it to string with
public static String XMLElementToString(Document doc, Element e) { // --- Output XML --- try { TransformerFactory transFactory = TransformerFactory.newInstance(); Transformer transformer = transFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); StringWriter buffer = new StringWriter(); Result result = new StreamResult(buffer); Source source = null; if (e != null) { transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); source = new DOMSource(e); } else { source = new DOMSource(doc); } transformer.transform(source, result); // <-- Error occurs here buffer.flush(); return buffer.toString(); } catch (TransformerException ex) { System.out.println("exception: " + ex.getMessage()); } return ""; }
I get an error with one of my objects. Using a breakpoint and looking through the xml object I cannot say why, although the TransformerException does say that the contained exception is a null pointer exception. It works on other related objects I have in the same program but I have no idea how to debug this.
[[EDIT]] Here is the stack trace:
ERROR: '' javax.xml.transform.TransformerException: java.lang.NullPointerException at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:716) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:313) at com.protocase.utils.StringHelpers.XMLElementToString(StringHelpers.java:132) at com.protocase.io.PDWriter.writePD(PDWriter.java:49) at com.protocase.io.PDWriter.writePDA(PDWriter.java:26) at com.protocase.viewer.JDesigner.OnSaveAs(JDesigner.java:1364) at com.protocase.viewer.JDesigner.access$000(JDesigner.java:106) at com.protocase.viewer.JDesigner$34.actionPerformed(JDesigner.java:722) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995) at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236) at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:272) at java.awt.Component.processMouseEvent(Component.java:6288) at javax.swing.JComponent.processMouseEvent(JComponent.java:3267) at java.awt.Component.processEvent(Component.java:6053) at java.awt.Container.processEvent(Container.java:2041) at java.awt.Component.dispatchEventImpl(Component.java:4651) at java.awt.Container.dispatchEventImpl(Container.java:2099) at java.awt.Component.dispatchEvent(Component.java:4481) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168) at java.awt.Container.dispatchEventImpl(Container.java:2085) at java.awt.Window.dispatchEventImpl(Window.java:2478) at java.awt.Component.dispatchEvent(Component.java:4481) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:643) at java.awt.EventQueue.access$000(EventQueue.java:84) at java.awt.EventQueue$1.run(EventQueue.java:602) at java.awt.EventQueue$1.run(EventQueue.java:600) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98) at java.awt.EventQueue$2.run(EventQueue.java:616) at java.awt.EventQueue$2.run(EventQueue.java:614) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) at java.awt.EventQueue.dispatchEvent(EventQueue.java:613) at com.protocase.viewer.EventQueueProxy.dispatchEvent(JDesigner.java:2338) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) Caused by: java.lang.NullPointerException at com.sun.org.apache.xml.internal.serializer.ToUnknownStream.characters(ToUnknownStream.java:338) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:240) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:226) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:226) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:226) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:226) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:132) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:94) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:661) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707) ... 45 more --------- java.lang.NullPointerException at com.sun.org.apache.xml.internal.serializer.ToUnknownStream.characters(ToUnknownStream.java:338) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:240) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:226) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:226) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:226) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:226) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:132) at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:94) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:661) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:313) at com.protocase.utils.StringHelpers.XMLElementToString(StringHelpers.java:132) at com.protocase.io.PDWriter.writePD(PDWriter.java:49) at com.protocase.io.PDWriter.writePDA(PDWriter.java:26) at com.protocase.viewer.JDesigner.OnSaveAs(JDesigner.java:1364) at com.protocase.viewer.JDesigner.access$000(JDesigner.java:106) at com.protocase.viewer.JDesigner$34.actionPerformed(JDesigner.java:722) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995) at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236) at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:272) at java.awt.Component.processMouseEvent(Component.java:6288) at javax.swing.JComponent.processMouseEvent(JComponent.java:3267) at java.awt.Component.processEvent(Component.java:6053) at java.awt.Container.processEvent(Container.java:2041) at java.awt.Component.dispatchEventImpl(Component.java:4651) at java.awt.Container.dispatchEventImpl(Container.java:2099) at java.awt.Component.dispatchEvent(Component.java:4481) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168) at java.awt.Container.dispatchEventImpl(Container.java:2085) at java.awt.Window.dispatchEventImpl(Window.java:2478) at java.awt.Component.dispatchEvent(Component.java:4481) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:643) at java.awt.EventQueue.access$000(EventQueue.java:84) at java.awt.EventQueue$1.run(EventQueue.java:602) at java.awt.EventQueue$1.run(EventQueue.java:600) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98) at java.awt.EventQueue$2.run(EventQueue.java:616) at java.awt.EventQueue$2.run(EventQueue.java:614) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) at java.awt.EventQueue.dispatchEvent(EventQueue.java:613) at com.protocase.viewer.EventQueueProxy.dispatchEvent(JDesigner.java:2338) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
-
jtahlborn about 12 yearsyou should at least include the link to the source of this suggestion (which @SajanChandran provided in his comment to the OP).
-
Fraser about 12 yearsSorry I added that in an edit after reading the link, missed the url..thought it was obvious. My main point was if it is a specific object causing the error then it is something specific about that object, invalid xml, etc
-
vextorspace about 12 yearsSo the transformer can't handle null text nodes? What does a null text node look like when you are looking at the xml? Is there any way of making the transformer robust to these things?
-
Fraser about 12 yearsThe offending node will likly be "<type/>" with no corresponding closing element. It will be some element that is not always written to. The best way is to just make sure the node has an empty string, so you have "<type></type>" rather than "<type/>"
-
Fraser about 12 yearsI think empty here means null, i.e. a node in the short form <data/>
-
LarsH about 12 years@Fraser: if that were true, the library would indeed be seriously buggy, and the OP would be at the mercy of his input.
<type/>
does not need a closing tag in XML; it's self-closing. A conforming XML parser will parse<type/>
and<type></type>
the same way. -
LarsH about 12 years@Fraser, I'm not sure which instance of "empty" you're referring to. In the above when I say "null" I'm referring to a null pointer, which is not valid input to
transformer.transform()
. A short form XML element like<data/>
should never produce a null pointer on parsing. -
LarsH about 12 years@Fraser, P.S., when I say "empty" above I'm referring to a string that is an actual object (not null) but contains zero characters, i.e.
""
. -
Fraser about 12 years@LarsH - hmm you are right of-course - I was speculating as to why the node has a null value, what to look for in the XML (ie. a node with no value)
-
LarsH about 12 yearsOK. Not a bad guess, but I'm sure that if there were a not-well-formed XML file, e.g. if you had a
<type>
start tag without a closing tag</type>
, then the parsing step would fail, beforedoc
ore
were ever passed to XMLElementToString().doc
ande
are node (tree)s, not serialized XML, so they have no tags. -
vextorspace about 12 yearsThanks, this was very helpful!
-
vextorspace about 12 yearsThanks, this was also very helpful and had some extra detail that was very nice!
-
Fraser about 12 years@vextorspace no worries, ooi what was the root of the issue?
-
Fraser about 12 years@LarsH - again true, but then whence the error? puzzling - if the error is only on a certain objects, that is the code given works as intended in all other cases, then I would look for a difference in the data structure, format, etc, of the object causing the error.
-
vextorspace about 12 yearsIt was in fact null text nodes - the internal sun methods in sun XMLSerializer deal with these the same as empty text nodes but not the sun XMLSerializer. I find it odd that the code would just give an exception for this case.
-
Jeremy over 9 yearsThis worked like a champ for me it actually helped me find an error in my xml.