beckchr/staxon

Bug when XML has \n in it!

Opened this issue · 13 comments

Hi,

If I execute a transformation from XML to JSON with the following:

        final JsonXMLConfig config = new JsonXMLConfigBuilder().virtualRoot(METADATAS).build();

        String input = "<metadatas>\n  <?xml-multiple metadata?>\n</metadatas>";

        System.out.println("XML : " + input);

        XMLEventReader reader = XMLInputFactory.newInstance()
                .createXMLEventReader(new ByteArrayInputStream(input.getBytes()));

        final OutputStream output = new ByteArrayOutputStream();
        /*
         * Create writer (JSON).
         */
        XMLEventWriter writer = new JsonXMLOutputFactory(config).createXMLEventWriter(output);

        /*
         * Copy events from reader to writer.
         */
        writer.add(reader);

        System.out.println("XML --> JSON : " + output.toString());

I get the following error:

java.lang.IllegalStateException: Nesting problem.
	at com.google.gson.stream.JsonWriter.beforeName(JsonWriter.java:616)
	at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:401)
	at com.google.gson.stream.JsonWriter.value(JsonWriter.java:417)
	at de.odysseus.staxon.json.stream.gson.GsonStreamTarget.value(GsonStreamTarget.java:61)
	at de.odysseus.staxon.json.stream.util.StreamTargetDelegate.value(StreamTargetDelegate.java:52)
	at de.odysseus.staxon.json.JsonXMLStreamWriter.writeEndElementTag(JsonXMLStreamWriter.java:203)
	at de.odysseus.staxon.base.AbstractXMLStreamWriter.writeEndElement(AbstractXMLStreamWriter.java:217)
	at de.odysseus.staxon.event.SimpleXMLEventWriter.add(SimpleXMLEventWriter.java:60)
	at de.odysseus.staxon.event.SimpleXMLEventWriter.add(SimpleXMLEventWriter.java:119)
	at org.ow2.petals.binding.rest.exchange.JSONHelperTest.test(JSONHelperTest.java:181)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

But if I use as input instead: <metadatas><?xml-multiple metadata?></metadatas> then it works without problem!

Hm, but maybe it is a bug in gson actually…

but I don't see how, since the only thing that differs is the XML which gson does know nothing about…

I am using gson 2.8.0 but it appears also with the version in staxon-gson.

Note the bug is not visible when using the default json serializer

Did you try jackson or staxon's built-in json support instead of gson?

let me try with jackson, but with built-in it works

it does work with jackson, so the problem only appears with gson.

But I don't see how adding carriage return to the XML should be visible to gson, shouldn't staxon abstract that?

ah no sorry, I didn't try, I made a mistake… I will tell you

Here is a stacktrace with Jackson…

javax.xml.transform.TransformerException: org.xml.sax.SAXException: Cannot write end element: metadatas
javax.xml.stream.XMLStreamException: Cannot write end element: metadatas
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:758)
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:359)
	at org.ow2.petals.binding.rest.exchange.JSONHelper.convertXMLToJSON(JSONHelper.java:85)
	at org.ow2.petals.binding.rest.exchange.JSONHelperTest.carriageReturnInXML(JSONHelperTest.java:338)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.xml.sax.SAXException: Cannot write end element: metadatas
javax.xml.stream.XMLStreamException: Cannot write end element: metadatas
	at com.sun.org.apache.xalan.internal.xsltc.trax.SAX2StAXStreamWriter.endElement(SAX2StAXStreamWriter.java:209)
	at com.sun.org.apache.xml.internal.serializer.ToXMLSAXHandler.endElement(ToXMLSAXHandler.java:265)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2973)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:650)
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:746)
	... 26 more
Caused by: javax.xml.stream.XMLStreamException: Cannot write end element: metadatas
	at de.odysseus.staxon.json.JsonXMLStreamWriter.writeEndElementTag(JsonXMLStreamWriter.java:214)
	at de.odysseus.staxon.base.AbstractXMLStreamWriter.writeEndElement(AbstractXMLStreamWriter.java:217)
	at com.sun.org.apache.xalan.internal.xsltc.trax.SAX2StAXStreamWriter.endElement(SAX2StAXStreamWriter.java:205)
	... 39 more
Caused by: com.fasterxml.jackson.core.JsonGenerationException: Can not write a field name, expecting a value
	at com.fasterxml.jackson.core.JsonGenerator._reportError(JsonGenerator.java:1897)
	at com.fasterxml.jackson.core.json.UTF8JsonGenerator.writeFieldName(UTF8JsonGenerator.java:185)
	at de.odysseus.staxon.json.stream.jackson.JacksonStreamTarget.name(JacksonStreamTarget.java:45)
	at de.odysseus.staxon.json.JsonXMLStreamWriter.writeEndElementTag(JsonXMLStreamWriter.java:201)
	... 41 more
---------
org.xml.sax.SAXException: Cannot write end element: metadatas
javax.xml.stream.XMLStreamException: Cannot write end element: metadatas
	at com.sun.org.apache.xalan.internal.xsltc.trax.SAX2StAXStreamWriter.endElement(SAX2StAXStreamWriter.java:209)
	at com.sun.org.apache.xml.internal.serializer.ToXMLSAXHandler.endElement(ToXMLSAXHandler.java:265)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2973)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:650)
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:746)
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:359)
	at org.ow2.petals.binding.rest.exchange.JSONHelper.convertXMLToJSON(JSONHelper.java:85)
	at org.ow2.petals.binding.rest.exchange.JSONHelperTest.carriageReturnInXML(JSONHelperTest.java:338)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: javax.xml.stream.XMLStreamException: Cannot write end element: metadatas
	at de.odysseus.staxon.json.JsonXMLStreamWriter.writeEndElementTag(JsonXMLStreamWriter.java:214)
	at de.odysseus.staxon.base.AbstractXMLStreamWriter.writeEndElement(AbstractXMLStreamWriter.java:217)
	at com.sun.org.apache.xalan.internal.xsltc.trax.SAX2StAXStreamWriter.endElement(SAX2StAXStreamWriter.java:205)
	... 39 more
Caused by: com.fasterxml.jackson.core.JsonGenerationException: Can not write a field name, expecting a value
	at com.fasterxml.jackson.core.JsonGenerator._reportError(JsonGenerator.java:1897)
	at com.fasterxml.jackson.core.json.UTF8JsonGenerator.writeFieldName(UTF8JsonGenerator.java:185)
	at de.odysseus.staxon.json.stream.jackson.JacksonStreamTarget.name(JacksonStreamTarget.java:45)
	at de.odysseus.staxon.json.JsonXMLStreamWriter.writeEndElementTag(JsonXMLStreamWriter.java:201)
	... 41 more
---------
javax.xml.stream.XMLStreamException: Cannot write end element: metadatas
	at de.odysseus.staxon.json.JsonXMLStreamWriter.writeEndElementTag(JsonXMLStreamWriter.java:214)
	at de.odysseus.staxon.base.AbstractXMLStreamWriter.writeEndElement(AbstractXMLStreamWriter.java:217)
	at com.sun.org.apache.xalan.internal.xsltc.trax.SAX2StAXStreamWriter.endElement(SAX2StAXStreamWriter.java:205)
	at com.sun.org.apache.xml.internal.serializer.ToXMLSAXHandler.endElement(ToXMLSAXHandler.java:265)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2973)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:650)
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:746)
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:359)
	at org.ow2.petals.binding.rest.exchange.JSONHelper.convertXMLToJSON(JSONHelper.java:85)
	at org.ow2.petals.binding.rest.exchange.JSONHelperTest.carriageReturnInXML(JSONHelperTest.java:338)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: com.fasterxml.jackson.core.JsonGenerationException: Can not write a field name, expecting a value
	at com.fasterxml.jackson.core.JsonGenerator._reportError(JsonGenerator.java:1897)
	at com.fasterxml.jackson.core.json.UTF8JsonGenerator.writeFieldName(UTF8JsonGenerator.java:185)
	at de.odysseus.staxon.json.stream.jackson.JacksonStreamTarget.name(JacksonStreamTarget.java:45)
	at de.odysseus.staxon.json.JsonXMLStreamWriter.writeEndElementTag(JsonXMLStreamWriter.java:201)
	... 41 more

Okay thanks. Will have to investigate this...

@beckchr anything I can do to help narrow the source of this problem? If you have ideas where I could look, I can start digging :)

The problem is, that the event reader passes whitespace as character event to the writer. I'm not sure how to fix this without unwanted side effects (ignoring whitespace when I shouldn't).

For now, the easiest thing may be to ignore whitespace completely. You can do this by adding an EventFilter to your event reader like this:

reader = XMLInputFactory.newInstance().createFilteredReader(reader, new EventFilter() {
    @Override
    public boolean accept(XMLEvent event) {
      return !event.isCharacters() || !event.asCharacters().isWhiteSpace();
    }
});

Hope that helps.

@beckchr thanks for the idea!