【问题标题】:How to mimic XPath 2.0 functions by lxml extension functions?如何通过 lxml 扩展函数模拟 XPath 2.0 函数?
【发布时间】:2023-04-02 04:52:02
【问题描述】:

我正在关注 lxml documentation on extension functions 并想在 XPath 2.0 中模仿 upper-case 函数。

import urllib
from lxml import html, etree

ns = etree.FunctionNamespace(None)
ns['upper-case'] = lambda context, s: str.upper(s)

google_page = urllib.request.urlopen('http://www.google.com').read().decode('latin-1')
google_page_tree = html.fromstring(google_page)

# text == ['Google.com']
text = google_page_tree.xpath('//a[@id="fehl"]/text()')

# TypeError: descriptor 'upper' requires a 'str' object but received a 'list'
text = google_page_tree.xpath('//a[upper-case(@id)="FEHL"]/text()')    

这似乎不是正确的方法,因为我看到 upper-case 收到了一个空列表 []。有任何想法吗?谢谢。

【问题讨论】:

    标签: python xpath lxml


    【解决方案1】:

    我不熟悉您的 XPath API,但@id 在 XPath 1.0 中选择了具有单个属性节点的节点集,而在 XPath 2.0 中选择了具有单个属性节点的序列。我假设str.upper 方法需要一个字符串值,因此请尝试//a[upper-case(string(@id)) = ...] 而不是//a[upper-case(@id) = ...]。这样,XPath 表达式应该产生一个 Python 函数知道要使用的字符串。

    【讨论】:

      【解决方案2】:

      您不需要模仿 xpath 2.0 的功能。您可以通过elementpath 将它们与 lxml 一起使用。

      如果你的 python 是 3.6+,只需用 pip 安装它

          pip install elementpath
      

      然后,导入 elementpath 和 lxml。

          import elementpath
          from lxml import etree
          root = etree.XML("<book name='sense and sensibility'/>")
          elementpath.select(root, "upper-case(@name)")
      

      这将产生:

          'SENSE AND SENSIBILITY'
      

      如果您的 xpath 返回节点,则返回类型是 lxml.etree._Element 的列表。因此,您可以将elementpath 视为lxml 的扩展。

      参考:

      elementpath docs

      XQuery 1.0 and XPath 2.0 Functions and Operators (Second Edition)

      What's New in XPath 2.0

      【讨论】:

        猜你喜欢
        • 2015-08-02
        • 2021-10-26
        • 2021-09-14
        • 1970-01-01
        • 2022-11-04
        • 1970-01-01
        • 1970-01-01
        • 2023-02-26
        • 2015-02-27
        相关资源
        最近更新 更多