问题
I would like to copy multiple XML nodes from a source XML file to a target file. Both source and target files are very large, so I will use StAX. Typically the file I'm trying to process looks as follows:
<root>
<header>
<title>A List of persons</title>
</header>
<person>
<name>Joe</name>
<surname>Bloggs</surname>
</person>
<person>
<name>John</name>
<surname>Doe</surname>
</person>
.
.
etc...
</root>
The target files should be in the following format:
<root>
<header>
<title>A List of persons</title>
</header>
<person>
<name>Joe</name>
<surname>Bloggs</surname>
</person>
</root>
where each file should contain the header node, exactly one person node all enclosed within the root node.
Now my problem is the following: I'm trying to read in the source file through a XMLStreamReader, and writing it using a XMLStreamWriter, both of which are wired into a Transformer instance which copies fragments from the source file into the target file. The transformer is created as follows:
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
StAXSource stAXSource = new StAXSource(reader);
StAXResult stAXResult = new StAXResult(writer);
I also have a custom made method which moves the cursor to the desired fragment in the XML input stream:
// Moves XMLStreamReader cursor to the next fragment.
moveCursorToNextFragment(XMLStreamReader reader, String fragmentNodeName)
So that in the end I end up with the following:
// Open file as usual...
// Advance cursor to <header> node, and copy fragment till
// </header> to the output writer.
moveCursorToNextFragment(reader, "header");
transformer.transform(stAXSource, stAXResult);
// Advance cursor to <person> node, and copy fragment till
// </person> to the output writer.
moveCursorToNextFragment(reader, "person");
transformer.transform(stAXSource, stAXResult);
The problem is that the resultant XML file contains 2 XML declaration sections, one for each invocation of
transformer.transform(stAXSource, stAXResult);
I have tried using StreamResult to transform the output, as follows:
transformer.transform(stAXSource, new StreamResult(myStream));
and the XML declaration is omitted, but when I reverted back to using StAXResult, the XML declaration is back again. I also noticed that OutputKeys.OMIT_XML_DECLARATION has no effect whether it is on or off (as are other settings such as OutputKeys.STANDALONE with a value of "yes").
So in short, it seems that these settings set globally on the Transformer are being disregarded when a StAXResult as a destination result.
My question is this: is there any way in which this can be achieved, so that the Transformer does not emit XML declarations upon each invocation of Transformer.transform() (i.e write fragments without the XML declaration)?
Your help is much appreciated and needed.
回答1:
Xalan's SAX2StAXStreamWriter
is doing this. Another XSLT implementation may behave differently. To get around this, you may wrap your writer and force the startDocument(...)
methods to do nothing. The StAXON library provides the StreamWriterDelegate utility class which helps to keep the necessary code short:
writer = new StreamWriterDelegate(writer) {
@Override public void writeStartDocument() {}
@Override public void writeStartDocument(String version) {}
@Override public void writeStartDocument(String encoding, String version) {}
};
should do the trick.
来源:https://stackoverflow.com/questions/9598345/omitting-xml-declaration-when-invoking-transformer-with-staxresult