How do I prevent a pair of XMLEvent[Reader|Writer] from splitting empty tags into start+end tags?
-
19-09-2019 - |
Question
I have an understanding problem of how the following code works:
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLOutputFactory xof = XMLOutputFactory.newFactory();
XMLEventReader reader = xif.createXMLEventReader(/* ... */);
XMLEventWriter writer = xof.createXMLEventWriter(/* ... */);
writer.add(reader);
The method writer.add([some reader]) reads all events from reader and writes them consequently. Sadly, following happens:
The input
<root><c/></root>
gets transformed to
<root><c><c/></root>
I know, from XML point of view, these are equal trees, but not for a human ;)
What can I do to get the same output?
FYI: I need a XMLEvent[Reader|Writer] pair later to filter "XML events".
Solution
According to the list of XMLEvents it seems like there is no way to make the distinction and it will indeed generate a StartElement
and EndElement
event. The consumer would need to optimize for the case when a StartElement
is immediately followed by an EndElement
.
This is apparently not the case of the XMLEventReader
returned by the factory. If you want to optimize this behavior yourself, I see no other way than to do something like
- check what's the concrete
XMLEventReader
implementation returned bycreateXMLEventReader
- subclass the
XMLEventReader
implementation to optimize this case - subclass
XMLInputFactory
and overridecreateXMLEventReader
to return an instance of yourXMLEventReader
subclass
If this sounds too complicated (or doesn't work), I would suggest that you go with a solution that uses XMLStreamWriter
. This one has a dedicated method writeEmptyElement
.
(Or you can give a try to my home-made pretty printer, it's based on XMLStreamWriter
)
OTHER TIPS
Unless I am mistaken, Woodstox can be configured to either produce empty tags (default), or not (so it'll always output start+end tag, even if there is no content). Since you can configure this for XMLStreamWriter, and you can then produce XMLEventWriter using that stream writer, it should work as expected.