我想将多个 XML 节点从源 XML 文件复制到目标文件。源文件和目标文件都非常大,所以我将使用 StAX。通常,我尝试处理的文件如下所示:
<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>
目标文件应采用以下格式:
<root>
<header>
<title>A List of persons</title>
</header>
<person>
<name>Joe</name>
<surname>Bloggs</surname>
</person>
</root>
其中每个文件应包含 header 节点,恰好有一个 person 节点,全部包含在 root 节点内。
现在我的问题如下:我尝试通过 XMLStreamReader 读取源文件,并使用 XMLStreamWriter 写入它,这两个文件都连接到复制片段的 Transformer 实例中从源文件到目标文件。变压器创建如下:
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);
我还有一个自定义方法,可将光标移动到 XML 输入流中所需的片段:
// Moves XMLStreamReader cursor to the next fragment.
moveCursorToNextFragment(XMLStreamReader reader, String fragmentNodeName)
所以最终我得到以下结果:
// 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);
问题是生成的 XML 文件包含 2 个 XML 声明部分,每次调用一个
transformer.transform(stAXSource, stAXResult);
我尝试使用StreamResult来转换输出,如下所示:
transformer.transform(stAXSource, new StreamResult(myStream));
并且 XML 声明被省略,但是当我恢复使用 StAXResult 时,XML 声明又回来了。我还注意到,OutputKeys.OMIT_XML_DECLARATION 无论打开还是关闭都没有任何影响(其他设置如 OutputKeys.STANDALONE 的值为“yes”)。
简而言之,当 StAXResult 作为目标结果时,在 Transformer 上全局设置的这些设置似乎被忽略。
我的问题是:有什么方法可以实现这一点,以便 Transformer 在每次调用 Transformer.transform() 时不会发出 XML 声明(即写入没有 XML 声明的片段)?
非常感谢并需要您的帮助。
最佳答案
Xalan 的 SAX2StAXStreamWriter
正在执行此操作。另一个 XSLT 实现的行为可能有所不同。为了解决这个问题,您可以包装您的编写器并强制 startDocument(...)
方法不执行任何操作。 StAXON图书馆提供 StreamWriterDelegate
实用程序类有助于保持必要的代码简短:
writer = new StreamWriterDelegate(writer) {
@Override public void writeStartDocument() {}
@Override public void writeStartDocument(String version) {}
@Override public void writeStartDocument(String encoding, String version) {}
};
应该可以解决问题。
关于xml-parsing - 使用 StAXResult 调用 Transformer 时省略 XML 声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9598345/