我听说https://stackoverflow.com/a/39560454中的HTML文档不是XML文档。
XPath和XQuery可处理XML文档。它们可以处理HTML文档吗?为什么?
尽管我不知道为什么,但是我猜XPath可以在HTML文档上使用,因为https://www.quora.com/Why-do-we-use-XPath-in-Selenium-even-though-CSS-Selector-is-faster和https://html-agility-pack.net/
(如果我也要问的话,是推荐它们在HTML文档上使用的推荐工具,还是推荐一些替代工具?如果不能,请忽略。)
谢谢。
答案 0 :(得分:6)
XQuery和XPath被定义为在称为XDM的特定数据模型上工作。在XPath 1.0中,这在XPath规范中进行了描述。在XQuery和更高版本的XPath中,它是在单独的规范中定义的。 XPath和XQuery可以在定义了XDM映射的任何数据上使用。 XML和HTML DOM在细节上与XDM都不同,但是可以(有点实用主义)定义到XDM的映射,因此XPath可以同时针对XML和HTML DOM运行。的确,尽管这两种映射不完善且在某些情况下效率不高,但它们的使用非常广泛。
HTML映射到XDM的最大问题是名称空间。传统上,XPath实现将HTML元素(例如“ table”和“ p”)视为没有命名空间,因此可以使用诸如//table//p
之类的路径而无需命名空间前缀。但是在HTML5中,WhatWG决定这些元素在XHTML命名空间中,这意味着它们必须定义XPath规范的变体以容纳此类路径。
CSS选择器已经慢慢获得了XPath 1.0的大部分表达能力,尽管它们肯定不如后来的版本丰富,并且由于它们主要是为HTML而不是XML设计的,因此有时使用起来更方便。我还没有看到任何性能数据,但是浏览器供应商必须付出很大的努力来使CSS更快,并且在过去的15年中,他们似乎在XPath实现上进行了几乎为零的开发,因此肯定不会。如果CSS在大多数浏览器中速度更快,我不会感到惊讶。 DOM和XDM之间的差异也会造成开销:值得注意的是,DOM中名称空间的表示效率非常低。
答案 1 :(得分:2)
HTML不能保证格式正确,因此XML解析器可能无法解析它(除非您使用的HTML子集非常有限)。但是,XHTML是HTML的格式良好的表亲,据我所知,它可以在具有相同功能集的浏览器中使用(请参阅:https://www.w3.org/TR/html-polyglot/)。
但是,如果您已经拥有HTML,则需要将其转换为XML以使用XPath / XQuery。有“ HTML tidy”的各种实现,可以选择输出有效的XML。 XQuery处理器中可能提供了某种整洁的形式。如果没有,那么可能有许多语言和独立的实现方式可以帮助您到达目的地。
答案 2 :(得分:2)
EXPath W3C社区有一个HTTP客户端模块的规范,该模块可从XPath和XQuery实现中访问,该实现执行HTML内容的“整理”。有关描述此内容的规范部分,请参见http://expath.org/spec/http-client#d2e517:
如果媒体类型是HTML类型,则将整理内容并进行解析(此过程取决于实现),并且该项目是结果文档节点。
现在,您可能认为将HTTP纳入查询HTML的问题有点a回,但是很自然地,人们可能想查询或遍历通过HTTP检索的HTML文档。它也符合不依赖于处理器的精神。
以下代码示例是标准XQuery,可在任何支持EXPath HTTP Client的XPath或XQuery实现上使用。它演示了如何检索HTML5文档(此处为HTML5规范本身,其未封闭的标签(如<meta>
使其格式不正确的XML)并通过XPath表达式进行查询:
xquery version "3.1";
declare namespace html = "http://www.w3.org/1999/xhtml";
import module namespace http = "http://expath.org/ns/http-client";
let $url := "https://www.w3.org/TR/html5/"
return
if (doc-available($url)) then
"The URL was well-formed XML. No tidying required. :)"
else
let $response := http:send-request(<http:request href="{$url}" method="GET"/>)
let $response-head := $response[1]
let $response-body := $response[2]
return
if (
$response-head/http:body/@media-type eq "text/html"
and $response-body instance of document-node()
) then
"The URL was an HTML document that was tidied into a "
|| "well-formed XML document. :) For example: "
|| $response-body//html:meta => head() => serialize()
else
"The HTTP Client wasn't able to parse the result "
|| "into a well-formed XML document. :("
这将返回:
The URL was an HTML document that was tidied into a well-formed XML document. :)
For example:
<html:meta
xmlns:html="http://www.w3.org/1999/xhtml"
http-equiv="Content-Type"
content="text/html; charset=utf-8"/>
请注意,此<meta>
元素是格式良好的XML,由XPath表达式//html:meta
生成。 (我在eXist中对此进行了测试。除了表达式为//meta
之外,相同的代码也可以在BaseX中工作,因为BaseX不会像eXist那样将整理好的HTML强制进入HTML名称空间。)
我应该补充一点,HTTP客户端规范将其留给处理器来定义“整理”,因此从一个实现到另一个实现肯定会有变化,但是如果问题是“ XPath和XQuery可以在HTML文档上工作吗?”,这表明它们可以并且只能做到与处理器无关的规范,并且在此证明了不同的实现可能对规范的不同理解。
答案 3 :(得分:1)
独立Xpath可以用于html文档。这样做的软件包/模块/应用程序的一些示例
答案 4 :(得分:1)
当我想在HTML文档上使用XPath(比XPath 1.0更高)时,我写了完整的XQuery interpreter for HTML。
除了标准的XQuery 3.0外,我还添加了一些可选的扩展名(实际上是不允许的,但对HTML有用),例如不区分大小写地匹配节点名称或使用名称空间更加轻松。