【问题标题】:JSoup parse attribute="value"=""JSoup 解析属性="值"=""
【发布时间】:2021-04-14 09:56:12
【问题描述】:

我的用例

  1. 从网站下载 HTML 文件
  2. 用 JSoup 解析它
  3. 使用 JSoup 将其转换为有效的 XML
  4. 使用 XPath (javax.xml.xpath) 从该 XML 文档中读取元素和属性

(这在大多数情况下已按预期实现和工作。)

问题/原因

有一种情况失败:

  1. 源 HTML 文件包含类似 <div someattribute="somevalue"=""></div> 的无效内容
  2. JSoup 将其转换为同样无效的字符串<div someattribute="somevalue" =""=""></div>
  3. XPath 无法解析无效的 JSoup 输出 XML。

问题和解决方法

  1. 是否可以给 JSoup 一个提示,以便它为这个无效输入生成有效输出?
  2. 是否可以给 XPath 一个提示,以便它解析无效输入(=JSoup 输出)?
  3. 是的,作为后备,我可以将无效的"="" 从 HTML 字符串中过滤出来,并将其替换为 ",但是当有一个可以解析无效 HTML 的库时,为什么要自己做呢!?

技术细节

不幸的是,我想通过 JSoup 解析的 HTML 文档包含类似 sn-p 的内容:

<div someattribute="somevalue"=""></div>

使用此配置调用 JSoup ...

Document doc = Jsoup.parse(html);
doc.outputSettings().syntax(Document.OutputSettings.Syntax.xml).charset(StandardCharsets.UTF_8);
String html = doc.html();

... 返回一个包含这个 sn-p 的 HTML 文档:

<div someattribute="somevalue" =""=""></div>

XPath 然后使用以下消息中止解析该文档:

Auf Elementtyp "div" müssen entweder Attributspezifikationen, ">" oder "/>" folgen.

英文是这样的:

Element type "div" must be followed by either attribute specifications, ">" or "/>".

【问题讨论】:

  • 感谢您的问题和详细信息。我在下面提供了一个解决方案,并在 jsoup 中提出了一个问题 (github.com/jhy/jsoup/issues/1474) 以跟踪确保 jsoup 的 XML 输出在这种情况下是有效的。

标签: java xpath jsoup


【解决方案1】:

jsoup 包含一个到 W3C DOM 模型的转换器,其中包括转换时的属性过滤。然后,您可以直接对该对象运行 xpath 查询,这不仅有效,而且比序列化为 XML 然后重新解析更有效。

请参阅org.jsoup.helper.W3CDom 的文档

这是一个例子:

import org.w3c.dom.Document;
import org.w3c.dom.Node;
...

String html = "<div someattribute=\"somevalue\"=\"\"></div>";
org.jsoup.nodes.Document jdoc = Jsoup.parse(html);
Document w3doc = W3CDom.convert(jdoc);

String query = "//div";
XPathExpression xpath = XPathFactory.newInstance().newXPath().compile(query);
Node div = (Node) xpath.evaluate(w3doc, XPathConstants.NODE);

System.out.printf("Tag: %s, Attribute: %s",
        div.getNodeName(),
        div.getAttributes().getNamedItem("someattribute"));

(注意这里的Document 和Node 是W3C DOM,而不是jsoup DOM。)

这给了我们:

Tag: div, Attribute: someattribute="somevalue"

【讨论】:

  • 好主意!这甚至可以解决我不必为 XPath 解析器转义/隐藏 JavaScript 代码的问题(背景信息:“if (a && b) {...}”是无效的 XML,因为 XPath 找不到 XML-第一个“&”之后的实体名称。为了解决这个问题,我将每个 script-element-HTML-content 替换为 "" 到现在为止。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-11
  • 2014-09-22
相关资源
最近更新 更多