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

4

10

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)
Takashi answered 5/2, 2012 at 15:23 Comment(7)
I get no trouble when I use the com.sun.org.apache.xml.internal.serialize.XMLSerializer instead, but it gives warnings about being a sun proprietary api and possibly being removed in future releasesTakashi
Please add full stack trace as that would make the problem more clear. Rather than ex.getMessage() do ex.printStackTrace().Vivyanne
The line where NPE is triggered is com.protocase.utils.StringHelpers.XMLElementToString(StringHelpers.java:132) Can you please underline in XMLElementToString method where line 132 is? ThanksEmbow
The line that the exception occurs at is transformer.transform(source, result);Takashi
This may help you dotcommers.wordpress.com/2008/10/22/…Townspeople
That is very interesting and somewhat enlightening. It gives me some idea as to where to look at least. This seems like a major flaw in the library however!dTakashi
@Takashi - it is a major flaw that it throws a NullPointerException when you pass it null data? how should a text-node with null content be handled?Breastpin
D
17

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.

Demivolt answered 14/2, 2012 at 20:27 Comment(10)
you should at least include the link to the source of this suggestion (which @SajanChandran provided in his comment to the OP).Breastpin
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, etcDemivolt
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?Takashi
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/>"Demivolt
@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.Balboa
@Balboa - 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)Demivolt
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.Balboa
@Takashi no worries, ooi what was the root of the issue?Demivolt
@Balboa - 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.Demivolt
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.Takashi
B
4

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?

Balboa answered 14/2, 2012 at 23:19 Comment(4)
I think empty here means null, i.e. a node in the short form <data/>Demivolt
@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.Balboa
@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. "".Balboa
Thanks, this was also very helpful and had some extra detail that was very nice!Takashi
H
4

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));
            }
        }
    }
Halide answered 23/8, 2012 at 8:25 Comment(1)
This worked like a champ for me it actually helped me find an error in my xml.Portmanteau
V
1

Yes, I was getting NPE in translator. Earlier I was using SAXON Parser and was working ok, but when I switched to com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl it, started failing. So before transformer.transform() I called this API deleteNullNode(Node node) ... and it worked like charm...

Verbify answered 27/1, 2023 at 16:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.