使用Java将HTML文件读入DOM树

使用Java将HTML文件读入DOM树,java,html,dom,parsing,Java,Html,Dom,Parsing,是否有能够使用Java将HTML文档读入DOM树的解析器/库?我想使用Java提供的标准DOM/XpathAPI 大多数库似乎都有自定义API来解决此任务。此外,大多数可用的解析器似乎都不支持将HTML转换为XML-DOM 使用一个好的HTML DOM解析器有什么想法或经验吗?应该做你想做的。可以通过将流处理成XHTML,然后使用你喜欢的DOM实现来重新解析,或者如果提供给你的有限DOM imp足够的话,可以使用parseDOM 或者。可以做您想做的。由于HTML文件通常有问题,您需要首先使用解

是否有能够使用Java将HTML文档读入DOM树的解析器/库?我想使用Java提供的标准
DOM/Xpath
API

大多数库似乎都有自定义API来解决此任务。此外,大多数可用的解析器似乎都不支持将HTML转换为XML-DOM

使用一个好的HTML DOM解析器有什么想法或经验吗?

应该做你想做的。

可以通过将流处理成XHTML,然后使用你喜欢的DOM实现来重新解析,或者如果提供给你的有限DOM imp足够的话,可以使用parseDOM


或者。

可以做您想做的。

由于HTML文件通常有问题,您需要首先使用解析器/扫描仪清理它们。我用过JTidy,但从来没有快乐过。NekoHTML工作正常,但这些工具中的任何一个都只是对其意图的最佳猜测。实际上,您要求让程序更改文档的标记,直到它符合模式。这可能会导致结构(标记)、样式或内容丢失。这是不可避免的,除非您通过浏览器手动扫描(然后您也必须信任浏览器),否则您不会真正知道缺少了什么

这真的取决于你的目的——如果你有成千上万个丑陋的文档和大量无关的(非HTML)标记,那么手动过程可能是不合理的。如果您的目标是对一些重要文档的准确性,那么手动修复它们是一个合理的建议

一种方法是手动过程,在编辑周期中使用错误消息反复将源代码传递给格式良好的和/或验证解析器,以最终修复损坏的标记。这确实需要对XML有一些了解,但这是一个不错的教育

使用Java5,必要的XML特性(称为JAXPAPI)现在内置到Java本身中;您不需要任何外部库

首先获取DocumentBuilderFactory的实例,设置其功能,创建DocumentBuilder(解析器),然后使用InputSource调用其parse()方法。InputSource有许多可能的构造函数,下面的示例中使用了StringReader:

import javax.xml.parsers.*;
// ...

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
dbf.setNamespaceAware(true);
dbf.setIgnoringComments(false);
dbf.setIgnoringElementContentWhitespace(false);
dbf.setExpandEntityReferences(false);
DocumentBuilder db = dbf.newDocumentBuilder();
return db.parse(new InputSource(new StringReader(source)));

这将返回一个DOM文档。如果您不介意使用外部库,还有JDOM和XOMAPI,虽然它们比JAXP中的SAX和DOM API有一些优势,但它们确实需要添加非Java库。DOM可能有些麻烦,但在使用了这么多年之后,我真的不再介意了

这里有一个可能有用的链接。这是一个在Java中使用的开源HTML解析器列表,它非常简单和强大。可以读取和更改HTML

样本:

Document doc = Jsoup.parse(page);  //page can be a file or string.
Element main = doc.getElementById("MainView");
Elements links = doc.select(".link");

因为create元素可以使用j2html,

Neko+Xerces做得很好。感谢所有的回答,小心JTidy。它有一个内存泄漏错误。如果你在生产系统中运行它,它最终会爆炸——StackOverflowerError,最终OutOfMemoryError。这就是说,它非常擅长修复损坏的html,以便您可以将其输入dom解析器。有没有一种干净的方法可以使用JTidy作为流式方式的JDOM或XOM前端?也就是说,不先将整个文档读入内存?(并且不使用PipedInput/OutputStream和多线程?)或者在这种情况下我使用Neko会更好吗?每个人都建议使用JTidy或其变体,但另一个需要注意的原因是,JTidy不是那么可预测的。你总是会从它那里得到警告,而且很难从洪流中判断页面是否真的是可处理的(我的经验是几年前的事),因为我记得它也很挑剔ampersands,我认为这比其他HTML故障更容易恢复。Xerces在验证方面非常严格,不适合阅读真实世界的HTML页面。我在XML中广泛使用JAXP,但我发现使用JAXP对HTML没有多大用处,即使在禁用验证或采取了您建议的其他步骤之后。但也许我试图解析的HTML离有效的XHTML太远了。