使用 StAXResult 调用 Transformer 时省略 XML 声明 [英] Omitting XML Declaration when invoking Transformer with StAXResult

查看:33
本文介绍了使用 StAXResult 调用 Transformer 时省略 XML 声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将多个 XML 节点从源 XML 文件复制到目标文件.源文件和目标文件都非常大,所以我将使用 StAX.通常,我尝试处理的文件如下所示:

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>

其中每个文件都应该包含 header 节点,恰好一个 person 节点都包含在 root 节点中.

where each file should contain the header node, exactly one person node all enclosed within the root node.

现在我的问题如下:我试图通过 XMLStreamReader 读取源文件,并使用 XMLStreamWriter 写入它,这两者都连接到一个复制 片段 的 Transformer 实例中从源文件到目标文件.转换器创建如下:

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);

我还有一个定制的方法,可以将光标移动到 XML 输入流中所需的片段:

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);

问题是生成的 XML 文件包含 2 个 XML 声明部分,每次调用一个

The problem is that the resultant XML file contains 2 XML declaration sections, one for each invocation of

transformer.transform(stAXSource, stAXResult);

我尝试使用 StreamResult 来转换输出,如下所示:

I have tried using StreamResult to transform the output, as follows:

transformer.transform(stAXSource, new StreamResult(myStream));

并且省略了 XML 声明,但是当我恢复使用 StAXResult 时,XML 声明又回来了.我还注意到 OutputKeys.OMIT_XML_DECLARATION 无论是打开还是关闭都没有影响(其他设置也是如此,例如值为yes"的 OutputKeys.STANDALONE).

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").

简而言之,当 StAXResult 作为目标结果时,这些在 Transformer 上全局设置的设置似乎被忽略了.

So in short, it seems that these settings set globally on the Transformer are being disregarded when a StAXResult as a destination result.

我的问题是:有什么方法可以实现这一点,以便 Transformer 在每次调用 Transformer.transform() 时都不会发出 XML 声明(即编写没有 XML 声明的片段)?

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.

推荐答案

Xalan 的 SAX2StAXStreamWriter 正在这样做.另一个 XSLT 实现的行为可能不同.为了解决这个问题,你可以包装你的 writer 并强制 startDocument(...) 方法什么都不做.StAXON 库提供了 StreamWriterDelegate 实用程序类,有助于保留必要的代码简短:

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) {}
};

应该可以解决问题.

这篇关于使用 StAXResult 调用 Transformer 时省略 XML 声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆