How do you debug an xml object that causes a transform error when writing to string?

22,292

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:

http://dotcommers.wordpress.com/2008/10/22/javaxxmltransformtransformerexception-javalangnullpointerexception-how-to-solve/

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));
            }
        }
    }
Share:
22,292
vextorspace
Author by

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, 2021

Comments

  • vextorspace
    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
    jtahlborn about 12 years
    you should at least include the link to the source of this suggestion (which @SajanChandran provided in his comment to the OP).
  • Fraser
    Fraser about 12 years
    Sorry 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
    vextorspace about 12 years
    So 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
    Fraser about 12 years
    The 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
    Fraser about 12 years
    I think empty here means null, i.e. a node in the short form <data/>
  • LarsH
    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
    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
    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
    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
    LarsH about 12 years
    OK. 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, before doc or e were ever passed to XMLElementToString(). doc and e are node (tree)s, not serialized XML, so they have no tags.
  • vextorspace
    vextorspace about 12 years
    Thanks, this was very helpful!
  • vextorspace
    vextorspace about 12 years
    Thanks, this was also very helpful and had some extra detail that was very nice!
  • Fraser
    Fraser about 12 years
    @vextorspace no worries, ooi what was the root of the issue?
  • Fraser
    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
    vextorspace about 12 years
    It 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
    Jeremy over 9 years
    This worked like a champ for me it actually helped me find an error in my xml.