XPath和XQuery可以在HTML文档上工作吗?

XPath和XQuery可以在HTML文档上工作吗?,html,xml,web,xpath,xquery,Html,Xml,Web,Xpath,Xquery,我听说HTML文档不是来自的XML文档 XPath和XQuery处理XML文档。他们能处理HTML文档吗?为什么 虽然我不知道为什么,但我想XPath可以用于HTML文档,因为和HTML不能保证格式良好,所以XML解析器可能无法解析它(除非您使用的是非常有限的HTML子集)。然而,XHTML是HTML格式良好的近亲,据我所知,它可以在具有相同功能集的浏览器中工作(请参阅:) 但是,如果您已经有了HTML,那么需要将其转换为XML以使用XPath/XQuery。“HTMLTidy”有多种实现,可以

我听说HTML文档不是来自的XML文档

XPath和XQuery处理XML文档。他们能处理HTML文档吗?为什么


虽然我不知道为什么,但我想XPath可以用于HTML文档,因为和

HTML不能保证格式良好,所以XML解析器可能无法解析它(除非您使用的是非常有限的HTML子集)。然而,XHTML是HTML格式良好的近亲,据我所知,它可以在具有相同功能集的浏览器中工作(请参阅:)


但是,如果您已经有了HTML,那么需要将其转换为XML以使用XPath/XQuery。“HTMLTidy”有多种实现,可以选择输出有效的XML。您的XQuery处理器中可能有某种形式的tidy。如果没有的话,有许多语言和独立的实现可以帮助您实现这一点。

XQuery和XPath被定义用于一个称为XDM的特定数据模型。在XPath 1.0中,这在XPath规范中进行了描述;在XQuery和更高版本的XPath中,它在单独的规范中定义。XPath和XQuery可以处理定义了XDM映射的任何数据。XML和HTMLDOM在许多细节上都与XDM不同,但是可以(有点实用主义)定义到XDM的映射,因此可以使XPath同时针对XML和HTMLDOM运行。事实上,这两种映射都得到了广泛的应用,尽管它们并不完美,在某些情况下效率低下

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中名称空间的表示效率非常低。

确实Xpath可以用于html文档。软件包/模块/应用程序的一些示例

  • 硒驱动器
  • python上的lxml(基于libxml2)
  • bash上的xmllint(基于libxml2)

EXPath W3C社区有一个HTTP客户机模块规范,可通过XPath和XQuery实现访问,该模块执行HTML内容的“整理”。请参阅本规范中描述这一点的章节:

如果媒体类型是HTML类型,则会整理和解析内容(此过程取决于实现),并且该项是生成的文档节点

现在,您可能会认为将HTTP引入查询HTML的问题有点迂回,但很自然的是,您可能想查询或遍历HTTP检索的HTML文档。它也符合处理器不可知论的精神

下面的代码示例是标准XQuery,可用于支持EXPath HTTP客户端的任何XPath或XQuery实现。它演示了如何检索HTML5文档(此处为HTML5规范本身,其未关闭的标记(如
)使其成为非格式良好的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. :("
xquery版本“3.1”;
声明命名空间html=”http://www.w3.org/1999/xhtml";
导入模块命名空间http=”http://expath.org/ns/http-client";
让$url:=”https://www.w3.org/TR/html5/"
返回
如果(文档可用($url)),则
“URL是格式正确的XML。无需整理:”
其他的
let$response:=http:send-request()
let$response head:=$response[1]
let$response body:=$response[2]
返回
如果(
$response head/http:body/@media type eq“text/html”
document-node()的$response body实例
)然后
“URL是一个HTML文档,已整理为”
||“格式正确的XML文档::)例如:”
||$response body//html:meta=>head()=>serialize()
其他的
“HTTP客户端无法分析结果”
||“转换为格式正确的XML文档:”
这将返回:

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"/>
URL是一个HTML文档,已整理成格式良好的XML文档。:)
例如:
请注意,这个
元素是格式良好的XML,由XPath表达式
//html:meta
生成。(我在eXist中测试了这一点。除了表达式是
//meta
之外,在BaseX中也可以使用相同的代码,因为BaseX不像eXist那样将整理好的HTML强制放到HTML命名空间中。)


我应该补充一点,HTTP客户机规范将定义“整理”留给处理器,因此不同的实现肯定会有所不同,但如果问题是“XPath和XQuery可以在HTML文档上工作吗?”,这表明它们可以,而且他们只能使用处理器无关的规范来实现这一点,这里证明了一点,即不同的实现可能会对规范进行不同的解释

当我想在HTML文档上使用XPath(比XPath 1.0更新)时,我编写了一个完整的

除了标准的XQuery3.0之外,我还添加了一些可选的扩展(实际上不允许,但对HTML很有用)