我听说HTML文档不是https://stackoverflow.com/a/39560454的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/
XQuery和XPath被定义为处理称为XDM的特定数据模型。在XPath 1.0中,这在XPath规范中描述;在XQuery和更高版本的XPath版本中,它在单独的规范中定义。 XPath和XQuery可以处理定义了XDM映射的任何数据。 XML和HTML DOM在XDM的许多细节上都有所不同,但是可以(有点实用主义)定义到XDM的映射,因此可以使XPath针对XML和HTML DOM运行。实际上,这两种映射都被广泛使用,即使它们不完美且在某些情况下效率低下。
HTML映射到XDM的最大问题是命名空间;传统上,XPath实现将诸如“table”和“p”之类的HTML元素视为没有名称空间,因此可以使用诸如//table//p
之类的路径,而不使用名称空间前缀。但是在HTML5中,WhatWG决定这些元素在XHTML命名空间中,这意味着他们必须定义XPath规范的变体以适应这些路径。
CSS选择器已经慢慢获得了XPath 1.0的大部分表现力,尽管它们肯定不像以后的版本那么丰富,并且因为它们主要是为HTML而不是XML而设计的,所以它们有时可以更方便地使用。我没有看到任何性能数据,但是浏览器厂商必须花费大量精力来快速制作CSS,并且他们似乎在过去的15年中对他们的XPath实现几乎没有开发,所以它肯定不会如果CSS在大多数浏览器中更快,我会感到惊讶。 DOM和XDM之间的差异也会产生开销:特别是DOM中命名空间的低效表示。
HTML不保证格式良好,因此XML解析器可能无法解析它(除非您使用非常有限的HTML子集)。但是,XHTML是HTML的良好表现,据我所知,在具有相同功能集的浏览器中工作(参见:https://www.w3.org/TR/html-polyglot/)。
但是,如果您已经拥有HTML,那么您需要将其转换为XML以使用XPath / XQuery。 “HTML tidy”有各种实现,可以选择输出应该有效的有效XML。您的XQuery处理器可能提供某种形式的整洁。如果没有,有许多语言和独立实现可能会让你到那里。
EXPath W3C社区有一个HTTP客户端模块的规范,可以从XPath和XQuery实现访问,执行HTML内容的“整理”。有关描述此内容的规范部分,请参阅http://expath.org/spec/http-client#d2e517:
如果媒体类型是HTML类型,则会对内容进行整理和解析(此过程与实现有关),该项目是生成的文档节点。
现在,您可能会认为将HTTP引入查询HTML的问题有点迂回,但人们可能想要查询或遍历通过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中对此进行了测试。相同的代码在BaseX中工作,除了表达式是//meta
,因为BaseX不会像eXist那样将整理的HTML强制转换为HTML命名空间。)
我应该补充说,HTTP客户端规范将它留给处理器来定义“整理”,所以肯定会有一个实现到另一个实现的变化,但如果问题是“XPath和XQuery可以在HTML文档上工作吗?”,这表明他们可以,并且他们只能处理器无关的规范 - 这里需要注意的是,不同的实现可能会以不同的方式解释规范。
事实上,Xpath可用于对付html文档。这样做的包/模块/应用程序的一些示例
当我想在HTML文档上使用XPath(比XPath 1.0更新)时,我写了一个完整的XQuery interpreter for HTML。
除了标准的XQuery 3.0之外,我还添加了一些可选的扩展(实际上不允许,但对HTML很有用),例如匹配节点名称不区分大小写或者使用名称空间更轻松。