寻求Java中类似C# HtmlAgilityPack的XPath HTML解析库及示例
Java中支持XPath 2.0/3.0的HTML解析方案(替代HtmlAgilityPack)
我明白你想要的是像C#的HtmlAgilityPack那样,既能轻松解析不规范HTML,又能直接用XPath(尤其是2.0/3.0版本)查询元素的Java工具。其实可以通过HTML解析器 + 支持XPath 2.0/3.0的处理器组合来实现,下面是具体的方案和可运行的示例:
依赖选择
我们需要两个核心库:
- Saxon-HE:这是一个强大的XSLT/XPath处理器,完全支持XPath 2.0,也兼容大部分XPath 3.0特性,是Java生态里支持高阶XPath的首选工具。
- TagSoup:专门用来解析不规范的HTML,将其转换成符合XML规范的W3C DOM,这样Saxon就能直接处理了。
如果用Maven,直接在pom.xml里添加这些依赖:
<dependencies> <!-- Saxon-HE 支持XPath 2.0/3.0查询 --> <dependency> <groupId>net.sf.saxon</groupId> <artifactId>Saxon-HE</artifactId> <version>12.4</version> </dependency> <!-- TagSoup 解析任意HTML为标准DOM --> <dependency> <groupId>org.ccil.cowan.tagsoup</groupId> <artifactId>tagsoup</artifactId> <version>1.2.1</version> </dependency> </dependencies>
完整示例代码
下面的代码演示了如何解析HTML,并用XPath 2.0的特性查询元素:
import net.sf.saxon.s9api.*; import org.xml.sax.InputSource; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import java.io.StringReader; public class HtmlXpathQueryExample { public static void main(String[] args) throws Exception { // 测试用的HTML内容(可以替换成你的目标HTML) String testHtml = """ <html> <head> <title>测试页面</title> </head> <body> <p class="article-content">这是第一篇文章的内容</p> <p class="article-content">第二篇文章,包含数字456</p> <div class="sidebar"> <p>侧边栏的提示文本</p> <p class="highlight">高亮的侧边栏内容</p> </div> </body> </html> """; // 第一步:用TagSoup把HTML解析成W3C DOM DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); docFactory.setNamespaceAware(false); // 关闭命名空间,避免HTML解析的额外麻烦 DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); // 禁用外部DTD加载,防止网络请求和解析错误 docBuilder.setEntityResolver((publicId, systemId) -> new InputSource(new StringReader(""))); Document htmlDoc = docBuilder.parse(new InputSource(new StringReader(testHtml))); // 第二步:初始化Saxon的XPath处理环境 Processor saxonProcessor = new Processor(false); DocumentBuilder saxonDocBuilder = saxonProcessor.newDocumentBuilder(); XdmNode rootNode = saxonDocBuilder.wrap(htmlDoc); // 第三步:编写并执行XPath 2.0查询 XPathCompiler xpathCompiler = saxonProcessor.newXPathCompiler(); // 示例1:选择所有class为article-content的p标签文本 String xpathExpr1 = "//p[@class='article-content']/text()"; XdmValue result1 = xpathCompiler.evaluate(xpathExpr1, rootNode); System.out.println("=== 示例1结果:所有article-content的p文本 ==="); for (XdmItem item : result1) { System.out.println(item.getStringValue()); } // 示例2:用XPath 2.0的matches()正则函数,筛选包含数字的p标签文本 String xpathExpr2 = "//p[matches(text(), '\\d+')]/text()"; XdmValue result2 = xpathCompiler.evaluate(xpathExpr2, rootNode); System.out.println("\n=== 示例2结果:包含数字的p文本 ==="); for (XdmItem item : result2) { System.out.println(item.getStringValue()); } // 示例3:用XPath 2.0的concat()函数,拼接class属性和文本内容 String xpathExpr3 = "//p/concat('Class: ', @class, ' | 内容: ', text())"; XdmValue result3 = xpathCompiler.evaluate(xpathExpr3, rootNode); System.out.println("\n=== 示例3结果:class与内容拼接 ==="); for (XdmItem item : result3) { System.out.println(item.getStringValue()); } } }
关键说明
- TagSoup的优势:它能处理各种不规范的HTML(比如未闭合的标签、大小写混乱的标签),输出标准的DOM结构,完美适配Saxon的XML处理能力。
- Saxon的XPath特性:除了示例里的
matches()和concat(),你还可以用XPath 2.0的其他特性,比如for表达式、序列操作、更强的字符串处理函数等。 - 替代方案:如果习惯用jsoup,也可以先jsoup解析HTML,再通过
Jsoup.w3cDocument()转成W3C DOM,然后交给Saxon处理,效果类似,但TagSoup的DOM转换更直接。
内容的提问来源于stack exchange,提问作者Heopas
相关产品推荐
相关产品推荐

