JSoup 解析属性="value"=""
JSoup parse attribute="value"=""
我的用例
- 从网站下载 HTML 文件
- 用 JSoup 解析它
- 使用 JSoup
将其转换为有效的 XML
- 使用 XPath (javax.xml.xpath)
从 XML 文档中读取元素和属性
(这已按预期实现并在大多数情况下有效。)
问题/原因
有一个失败案例:
- 源 HTML 文件包含类似这样的无效内容
<div someattribute="somevalue"=""></div>
- JSoup 将其转换为同样无效的字符串
<div someattribute="somevalue" =""=""></div>
- XPath 无法解析无效的 JSoup 输出 XML。
问题及解决方法
- 是否可以给 JSoup 一个提示,以便它为这个无效输入生成有效输出?
- 是否可以给 XPath 一个提示,以便它解析无效输入(=JSoup 输出)?
- 是的,作为后备,我可以从 HTML 字符串中过滤出无效的
"=""
并将其替换为 "
,但是当有一个库可以解析无效的HTML!?
技术细节
不幸的是,我想要由 JSoup 解析的 HTML 文档包含类似以下片段的内容:
<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();
...returns 包含此片段的 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 包括一个到 W3C DOM 模型的转换器,其中包括转换时的属性过滤。然后,您可以 运行 直接对该对象进行 xpath 查询,这不仅有效,而且比序列化到 XML 然后重新解析它更有效。
的文档
这是一个例子:
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"
我的用例
- 从网站下载 HTML 文件
- 用 JSoup 解析它
- 使用 JSoup 将其转换为有效的 XML
- 使用 XPath (javax.xml.xpath) 从 XML 文档中读取元素和属性
(这已按预期实现并在大多数情况下有效。)
问题/原因
有一个失败案例:
- 源 HTML 文件包含类似这样的无效内容
<div someattribute="somevalue"=""></div>
- JSoup 将其转换为同样无效的字符串
<div someattribute="somevalue" =""=""></div>
- XPath 无法解析无效的 JSoup 输出 XML。
问题及解决方法
- 是否可以给 JSoup 一个提示,以便它为这个无效输入生成有效输出?
- 是否可以给 XPath 一个提示,以便它解析无效输入(=JSoup 输出)?
- 是的,作为后备,我可以从 HTML 字符串中过滤出无效的
"=""
并将其替换为"
,但是当有一个库可以解析无效的HTML!?
技术细节
不幸的是,我想要由 JSoup 解析的 HTML 文档包含类似以下片段的内容:
<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();
...returns 包含此片段的 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 包括一个到 W3C DOM 模型的转换器,其中包括转换时的属性过滤。然后,您可以 运行 直接对该对象进行 xpath 查询,这不仅有效,而且比序列化到 XML 然后重新解析它更有效。
的文档这是一个例子:
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"