我正在尝试使用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 ... ?>
声明时,示例将通过。我在发布之前没有检查过,刚刚添加它。
答案 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(与上面相同的链接)。