重写 XML 文件时使用哪种 Java XML 解析方法?

Which Java XML Parsing method to use when rewriting an XML file?

为清楚起见进行了编辑。

我正在编写一个 Java 应用程序,它接受一个 XML 文件并在文件中的信息需要更新时重写它。 XML 文件的示例如下:

<!DOCTYPE book PUBLIC "myDTD.dtd" [

<!ENTITY % ent SYSTEM "entities.ent">
%ent;

]>

<book id="EXDOC" label="beta" lang="en">
   <title>Example Document</title>
   <bookinfo>
      <authorgroup>
         <author>
            <firstname>George</firstname>
            <surname>Washington</surname>
         </author>
         <author>
            <firstname>Barbara</firstname>
            <surname>Bush</surname>
         </author>
      </authorgroup>
      <pubsnumber>E12345</pubsnumber>
      <releaseinfo/>
      <pubdate>March 2016</pubdate>
      <copyright>
         <year>2012, 2016</year>
         <holder>Company and/or its affiliates. All rights reserved.</holder>
      </copyright>
      <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Abstract.xml" parse="xml"/>
      <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="legal.xml" parse="xml"/>
   </bookinfo>
   <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="preface.xml" parse="xml"/>
...

我需要抓取某些节点并检查该信息,如果信息不正确,则更新节点以具有正确的文本。我可能还想根据需要 add/remove 个节点。

例如,在节点中,我可能需要更改版权年份以列出最近的年份。或者,我可能需要向元素添加编写器。

此刻,我创建了一个 SAX 解析器的实例,验证 XML 文件以从该实例创建一个文档(它反过来解析任何实体),从文档中读取节点,然后使用 setTextContent() 方法更新文本。然后,我在特定文件的所有更新结束时获取生成的文档,并使用 DOMSource 和 Transformer 工厂输出我的文件:

 TransformerFactory transformerFactory;
 transformerFactory = TransformerFactory.newInstance();
 Transformer transformer = transformerFactory.newTransformer();
 DOMSource source = new DOMSource(doc);
 StreamResult result = new StreamResult(new File(uri));
 transformer.transform(source, result);

不过,这带来了一些限制,我真的很想绕过这些限制。其一,如果内联文本有一个文本实体 &something;,我想保持实体不变。目前,当文件被重写时,我的实体解析为文本本身。

例如,如果我有

<!ENTITY something "Something">

如果我的文件有类似的内容:

<para> There's a &something; here.</para>

当我重写时,我希望它说:

<para> Here's a &something; there.</para>

但实体解析后文件变为:

<para>Here's a Something there.</para>

我不确定如何处理我的 entityResolver class,这样当我读取节点时它不会自动解析这些实体而不会破坏我的其余代码。我还有另一个 class 与 XPATH 一起使用,它从文档中提取某些信息以将 XML 文件中的信息与数据库中记录的信息进行比较,所以我不能不设置 entityResolver否则 XPATH 表达式将完全中断。

我想我可以有一个单独的解析器用于 reading/writing 和 XML 文件,然后是从我们的数据库中获取信息所必需的 SAX 解析器,但我想这样做尽可能干净可能。

如有任何帮助,我们将不胜感激...

遗憾的是,您无法告诉转换引擎不要扩展实体引用。这种情况发生在解析 XML 时,因此在 XML 内容被转换时它们会丢失。

多阶段转换场景如何:

  1. entity-reference-like 标记替换实体引用,即用 ¶something;as Michael Kay suggested 替换 &something;
  2. 执行转换以根据需要调整内容,这不会扩展实体引用并将保留您的 entity-reference-like 标记。如果您确实需要解析实体以验证这些实体信息,您还可以加载原始 XML 文档(带有扩展实体)和文档之间的交叉引用。

  3. 将转换后的输出中的 entity-reference-like 标记改回另一个 find/replace.

    的实体引用