XPathEvalError: 在lxml中,matches()函数未注册

8
我将使用以下XPath查询语句在Python中进行尝试:
from lxml.html.soupparser import fromstring
root = fromstring(inString)
nodes = root.xpath(".//p3[matches(.,'ABC')]//preceding::p2//p3")

但是它给我报错了。
  nodes = root.xpath(".//p3[matches(.,'ABC')]//preceding::p2//p3")
  File "lxml.etree.pyx", line 1507, in lxml.etree._Element.xpath (src\lxml\lxml.etree.c:52198)
  File "xpath.pxi", line 307, in lxml.etree.XPathElementEvaluator.__call__ (src\lxml\lxml.etree.c:152124)
  File "xpath.pxi", line 227, in lxml.etree._XPathEvaluatorBase._handle_result (src\lxml\lxml.etree.c:151097)
  File "xpath.pxi", line 212, in lxml.etree._XPathEvaluatorBase._raise_eval_error (src\lxml\lxml.etree.c:150896)
  lxml.etree.XPathEvalError: Unregistered function

我该如何在lxml中使用XPath 2.0函数?

澄清

我之前使用了contains函数,例如:

nodes = root.xpath(".//p3[contains(text(),'ABC')]//preceding::p2//p3")

问题是我的XML文本中有换行符和空格,因此我尝试使用以下内容
nodes = root.xpath(".//p3[contains(normalize-space(),'ABC')]//preceding::p2//p3")

但这没有任何效果。最后我尝试使用matches函数,但是出现了错误。 示例 XML
<doc>

<q></q>

<p1>
    <p2 dd="ert" ji="pp">

        <p3>1</p3>
        <p3>2</p3>
        <p3>
               ABC
        </p3>
        <p3>3</p3>

     </p2>

     <p2 dd="ert" ji="pp">

        <p3>4</p3>
        <p3>5</p3>
        <p3>ABC</p3>
        <p3>6</p3>

     </p2>

</p1>
<r></r>
<p1>
    <p2 dd="ert" ji="pp">

        <p3>7</p3>
        <p3>8</p3>
        <p3>ABC
        </p3>
        <p3>9</p3>

     </p2>

     <p2 dd="ert" ji="pp">

        <p3>10</p3>
        <p3>11</p3>
        <p3>ABC</p3>
        <p3>12</p3>

     </p2>

</p1>
</doc>

请您提供一个示例的 XML 文件来展示这个问题吗?谢谢! - alecxe
当然,请查看更新。 - AbtPst
2个回答

11
如另一个答案所述,强调引用文档的另一部分,您可以使用EXSLT扩展来在lxml中拥有正则表达式match()函数,例如: match()
......
ns = {"re": "http://exslt.org/regular-expressions"}
nodes = root.xpath(".//p3[re:match(.,'ABC')]//preceding::p2//p3", namespaces=ns)

太好了!谢谢。我能让XPath查询变成可选的吗?也就是说,如果有一个<p2>没有<p3>ABC</p3>或<p3>XYZ</p3>,那么我仍然希望获取该<p2>中的所有<p3>。 - AbtPst

4

我如何在lxml中使用XPath 2.0函数?

你不能(参考):

lxml支持XPath 1.0,XSLT 1.0和EXSLT扩展,通过libxml2和libxslt以符合标准的方式实现。

contains()可能是你在这种情况下能够使用的最接近的方法:

.//p3[contains(., 'ABC')]//preceding::p2//p3

正确,我之前使用了“contains”,但我的XML文本中包含CR和LF,因此我无法正确选择节点。因此,我希望有类似于“matches”的东西。 - AbtPst

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