【问题标题】:Which Java XML Parsing method to use when rewriting an XML file?重写 XML 文件时使用哪种 Java XML 解析方法?
【发布时间】:2017-08-18 00:24:57
【问题描述】:

为清晰起见进行了编辑。

我正在编写一个 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"/>
...

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

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

目前,我创建了一个 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 类,这样当我读取节点时它不会自动解析这些实体,而不会破坏我的其余代码。我还有另一个与 XPATH 一起使用的类,它从文档中提取某些信息以将 XML 文件中的信息与数据库中记录的信息进行比较,所以我不能不设置 entityResolver,否则 XPATH 表达式会完全中断。

我想我可以有一个单独的解析器来读取/写入 XML 文件,然后是 SAX 解析器,它是从我们的数据库中获取信息所必需的,但我希望这样做尽可能干净。

任何帮助将不胜感激......

【问题讨论】:

  • 您应该为此使用 XSLT。
  • EJP - 在对数据库进行检查时 XSLT 是否可用?我以前从未使用过它,所以额外的信息会很有用。

标签: java xml xpath sax entities


【解决方案1】:

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

多阶段转换场景怎么样:

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

  3. 将转换后的输出中的 entity-reference-like 标记改回实体引用,并使用另一个查找/替换。

【讨论】:

  • 嗨,Mads,感谢您的回复。不幸的是,实体在被读取之前实际上已被解析。这是因为实体没有存储在数据库中。例如,如果我有一个 &ProductName 其中 &ProductName;解析为“公司的新产品名称”,数据库中只有“公司的新产品名称”。所以我不能使用实体令牌。
  • 经过一番折腾,在我解析文档之前使用引用标记非常有效!谢谢疯子!
猜你喜欢
  • 2011-07-21
  • 2015-10-26
  • 2015-08-25
  • 2011-12-15
  • 2013-12-24
  • 1970-01-01
  • 2012-12-25
  • 1970-01-01
  • 2015-05-14
相关资源
最近更新 更多