问题
I've got this code:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();
Document xmldoc = impl.createDocument(null, null, null);
Element root = xmldoc.createElement("root");
Element textElement = xmldoc.createElement("text");
Text textNode = xmldoc.createTextNode("");
root.appendChild(textElement);
textElement.appendChild(textNode);
OutputFormat of = new OutputFormat("XML","UTF-8",true);
of.setIndent(1);
of.setIndenting(true);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
XMLSerializer serializer = new XMLSerializer(stream, of);
// As a DOM Serializer
serializer.asDOMSerializer();
serializer.serialize(root);
System.out.println(stream.toString());
I get to console this:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<text/>
</root>
But, I'd like to get this:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<text></text>
</root>
Does anybody know, how to set the XMLSerializer to avoid Complex Empty Elements? Thanks.
回答1:
I had the same problem with XMLSerializer not allowing rendering customization of empty tags. My solution was to extend the original XMLSerializer code and override the serializeElement method:
I have copied the original code and changed the closing printing part:
protected void serializeElement(Element elem) throws IOException ...
if (isSelfClosingElement(elem))
_printer.printText("/>");
else
_printer.printText("></" + elem.getTagName() + ">");
where isSelfClosingElement holds a list of self closing elements
NOTE: additionally you need to copy the printAttribute() and printNamespaceAttr() method as it is marked private instead of protected.
回答2:
Outcome: I don't think it is possible. XMLSerializer does not support such configuration.
Analysis:
When you call serializer.serialize(root)
, BaseMarkupSerializer's serialize(Element) method is invoked. It defines type of node you pass to serialize and chooses appropriate way to deal with it.
When it comes to the text node, it calls XMLSerializer's serializeElement(Element) method:
// If element has children, then serialize them, otherwise
// serialize en empty tag.
if (elem.hasChildNodes()) {
//... irrelevant code...
endElementIO( null, null, tagName );
} else {
//... irrelevant code...
_printer.printText( "/>" ); // <------ HARDCODED, NON-CONFIGURABLE
//... irrelevant code...
}
Problem: As you can see, way of closing empty element is hardcoded and not configurable (if you look for complete code snippet from source code).
Solution: Since XMLSerializer is not final, you could create your own serializer by extending it and overriding it's method. One of the ways would be changing:
_printer.printText( "/>" );
to
_printer.printText( "</" );
_printer.printText( elem.getTagName() );
_printer.printText( ">" );
Opinion: I am not sure if there is no clean solution and I see this solution as the last resort solution. Anyway, you should look yourself through the sources and/or documentation for more information.
来源:https://stackoverflow.com/questions/10726974/java-xmlserializer-avoid-complex-empty-elements