JAXP解析有效XML上的错误

时间:2018-02-17 16:35:25

标签: java xpath jaxp

我正在尝试使用Java在XML上运行一些XPath查询,显然推荐的方法是首先构建一个文档。

以下是我使用的标准JAXP代码示例:

import org.w3c.dom.Document;
import javax.xml.parsers.*;

final DocumentBuilder xmlParser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document doc = xmlParser.parse(xmlFile);

我也尝试过Saxon API,但也遇到了同样的错误:

import net.sf.saxon.s9api.*;

final DocumentBuilder documentBuilder = new Processor(false).newDocumentBuilder();
final XdmNode xdm = documentBuilder.build(new File("out/data/blog.xml"));

以下是JDK 1.8中的DocumentBuilder无法解析的最小重构示例XML:

<?xml version="1.1" encoding="UTF-8" ?>
<xml>
    <![CDATA[Some example text with [funny highlight]]]>
</xml>

根据规范,在CDATA标记]结束之前的方括号]]>是完全合法的,但解析器只是以堆栈跟踪和消息org.xml.sax.SAXParseException; XML document structures must start and end within the same entity.退出。

在包含大量CDATA部分的原始数据文件中,消息为org.xml.sax.SAXParseException; The element type "item" must be terminated by the matching end-tag "</item>"。在这两种情况下,'com.sun.org.apache.xerces'都会在堆栈跟踪中显示出来。

形成两个观察结果似乎解析器只是没有结束]]>处的CDATA部分。

编辑:事实证明,当省略<?xml ... ?>声明时,示例将通过。我在发布之前没有检查过,刚刚添加它。

1 个答案:

答案 0 :(得分:1)

简短回答:将Apache Xerces添加到构建路径中,它将自动加载而不是JDK中的解析器,并且XML将被解析得很好!复制粘贴Gradle依赖关系:

implementation "xerces:xercesImpl:2.11.0"

一些背景知识:Apache Xerces确实是同样的解析器,它也用在JDK中,但即使Xerces 2.11的日期是2013年,JDK也会提供更旧的版本。真的太糟糕了!

正如撒克逊人团队所说:

  

Saxonica建议使用Apache中的Xerces解析器,而不是JDK中捆绑的版本,这已知有一些严重的错误。

如果您想知道如何简单地将Xerces放在类路径上会使问题消失:即使JDK和Saxon DocumentBuilders构造entirely different document types,它们都使用相同的标准Java接口来调用解析器,也使用相同的机制查找并加载解析器(或者更确切地说,解析器工厂)。简而言之,调用java.util.ServiceLoader并查看META-INF/services中属性文件的类路径中的所有JAR,这就是xercesJar宣布它确实提供XML解析器的方式。对我们有益,JDK自己的实现被那里发现的任何东西所取代。

在使用JDK XML类获得这种糟糕的体验之后,我更有动力重构项目以使用Saxon进行XPath处理而不是在JDK中实现XPath。另一个原因是technical advantage of XDM over DOM(与上面相同的链接)。