我必须用Java语言解析一大堆XML文件,这些文件有时包含—
、>
等HTML实体,但这些实体是无效的。我知道处理这个问题的正确方法是在解析之前向XML文件添加适当的实体声明。但是,我不能这样做,因为我无法控制这些XML文件。
是否存在某种我可以覆盖的回调,以便在Java XML解析器遇到这样的实体时被调用?我在API中找不到。
我想使用:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = dbf.newDocumentBuilder();
Document doc = parser.parse( stream );
我发现我可以在org.xml.sax.helpers.DefaultHandler
中覆盖resolveEntity
,但是如何在更高级别的API中使用它呢?
下面是一个完整的示例:
public class Main {
public static void main( String [] args ) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = dbf.newDocumentBuilder();
Document doc = parser.parse( new FileInputStream( "test.xml" ));
}
}
使用test.xml:
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar>Some text — invalid!</bar>
</foo>
产生:
[Fatal Error] :3:20: The entity "nbsp" was referenced, but not declared.
Exception in thread "main" org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 20; The entity "nbsp" was referenced, but not declared.
更新:我一直在用调试器查看JDK源代码,天哪,真是太麻烦了。我不知道那里有什么设计,或者是否有一个。一层洋葱能叠加多少层?
它们的关键类似乎是com.sun.org.apache.xerces.internal.impl.XMLEntityManager
,但我找不到任何代码,可以让我在使用它之前向它添加东西,或者尝试在不通过那个类的情况下解析实体。
发布于 2016-03-24 01:52:15
为此,我会使用像Jsoup这样的库。我在下面测试了一下,它是有效的。我不知道这有没有帮助。它可以在这里找到:http://jsoup.org/download
public static void main(String args[]){
String html = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><foo>" +
"<bar>Some text — invalid!</bar></foo>";
Document doc = Jsoup.parse(html, "", Parser.xmlParser());
for (Element e : doc.select("bar")) {
System.out.println(e);
}
}
结果:
<bar>
Some text — invalid!
</bar>
从文件加载可以在以下位置找到:
发布于 2016-03-24 01:18:32
另一种方法,因为您并没有使用严格的OXM方法。您可能想尝试使用不太严格的解析器,比如JSoup?这将立即停止无效XML模式等问题,但它只会将问题转移到您的代码中。
发布于 2016-03-19 03:08:32
只是为了给解决方案添加一种不同的方法:
您可以使用流实现封装您的输入流,该实现将实体替换为合法的实体。
虽然这肯定是一个技巧,但它应该是一个快速而简单的解决方案(或者更好地说:变通)。
不过,没有xml框架内部解决方案那么优雅和干净。
https://stackoverflow.com/questions/36026353
复制相似问题