XPath和XQuery能用于HTML文档吗?

6
5个回答

8
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
在StackOverflow上,关于技术选择的建议是不被允许的。这是有非常好的理由的,因为没有一个专业顾问会在没有深入研究您项目的要求和约束条件之后就给出选择建议。在这里得到的任何建议都只是某个人的个人意见,并且通常缺乏足够的信息支持。 - Michael Kay
@kjhughes 谢谢。请不用担心。感谢您提供的任何建议。不必担心准确性,我不会反感。我只是想知道学习XPath和XQuery是否值得,或者它们已被其他技术所取代。需要考虑到XML已经失去了应用领域,被JSON(和可能的HTML)所取代。 - Tim
1
@Tim:JSON 用于数据;XML 用于文档。但除了工具推荐之外,我不会再跟随你进入那个兔子洞了(除非一般地说,XPath 值得学习)。 - kjhughes
@kjhughes XQuery 值得学习吗?如果只处理 JSON 和 HTML,XPath 和 XQuery 的知识有多少可迁移性?我正在自学一本名为 Database System Concepts 的书,其中有一章关于 XML、XPath 和 XQuery,我在考虑是否值得花时间学习它们。 - Tim
1
@Tim,我们不可能知道你所在地区或未来职业生涯中将使用哪些技术。因此,我们无法提供职业建议。可以说,尽管XML不像以前那么时髦,但仍有大量相关内容在网络中传播。(实际上,一种成功的技术只有在过去20年后才会真正开始衰落)。 - Michael Kay
显示剩余4条评论

5
HTML不能保证良好的格式,因此XML解析器可能无法解析它(除非您正在使用非常有限的HTML子集)。但是,XHTML是HTML的格式良好的姊妹版本,并且据我所知在具有相同功能集的浏览器中可以正常工作(请参见:https://www.w3.org/TR/html-polyglot/)。
但是,如果您已经有HTML,则需要将其转换为XML才能使用XPath / XQuery。有各种实现“HTML整理”并选项输出有效XML的程序可用。某种程度上的整洁可能在您的XQuery处理器中可用。如果没有,则可能会有许多语言和独立实现可以帮助您完成这一点。

谢谢。 (1) 每个HTML文档都可以转换为等效的XHTML文档吗?(2) 虽然我不知道为什么,但我猜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转换为XHTML才能使用XPath? - Tim
@Tim 1) 我怀疑有一些例外,但通常来说是可以的。2) 网页浏览器解析HTML并构建类似于XML的DOM,因此您可以在JavaScript中使用XPath HTML,但不能使用XQuery或XSLT。这是否适用于您取决于您的应用程序。 - wst

3
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文档?”,那么这证明了它们可以,并且只能使用处理器无关的规范——但要注意不同的实现可能会以不同的方式解释规范。

2
当我想在HTML文档上使用XPath(比XPath 1.0更新)时,我编写了一个完整的用于HTML的XQuery解释器。除了标准的XQuery 3.0外,我还添加了一些可选扩展(尽管实际上不允许,但对于HTML很有用),例如不区分大小写地匹配节点名称或更宽松的命名空间。最初的回答。

谢谢。我可以问一下使用Xidel相对于BaseX(也许还有Saxon)的优缺点吗? - Tim
Xidel比basex/saxon小得多,是用Pascal编写的。所以它需要更少的空间。在小查询上,它应该更快,因为它可以在其他语言的Java虚拟机启动之前完成查询评估;但在运行时间较长的查询上,它会变得更慢,因为它没有太多优化。 - BeniBela

1

事实上,XPath 可以用于 HTML 文档。以下是一些使用 XPath 的软件包/模块/应用示例:

  • Selenium 驱动程序
  • Python 中的 lxml(基于 libxml2)
  • Bash 中的 xmllint(基于 libxml2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接