【问题标题】:XPath to select nodes in arbitrarily nested chains of a particular tagXPath 在特定标签的任意嵌套链中选择节点
【发布时间】:2020-05-13 08:45:47
【问题描述】:

在这样的例子中:

<body>

  <p id="0"/>

  <div>
    <p id="1"/>
  </div>

  <div>
    <div>
      <div>
        <p id="2"/>
      </div>
    </div>
  </div>

  <blockquote>
    <p id="3"/>
  </blockquote>

  <div>
    <blockquote>
      <div>
        <p id="4"/>
      </div>
    </blockquote>
  </div>

</body>

我想选择所有&lt;p&gt; 元素,它们要么是&lt;body&gt; 的直接子元素,要么只包含在&lt;div&gt; 元素链中,仅此而已。也就是说,我想选择 ids 0、1 和 2,而不是 3 或 4。在正则表达式中,这类似于 &lt;body&gt;(&lt;div&gt;)*&lt;p&gt;。但是这可以用 XPath 完成吗? body/p | body/div/p | body/div/div/p | body/div/div/div/p | ... 的一些简写?

ETA:请注意,id 属性仅出现在此示例中是为了方便,在我的实际应用程序中没有 ids。

另外,最终我会寻找一个可以使用任意节点作为参考的表达式(而不仅仅是&lt;body&gt;),即如何选择作为参考节点的后代的节点,但中间的任何中间级别他们是&lt;div&gt;,仅此而已。换一种说法,我想要其祖先都是 &lt;div&gt; 或特定引用节点的祖先或自身的节点(不仅仅是标签名称,而是特定节点)。

当我说“参考节点”时,我指的是要使用的东西,例如使用 Python lxml 包:

reference_node.xpath( problem_expression )

【问题讨论】:

    标签: xpath


    【解决方案1】:

    我想到的是:

    //p[count(ancestor::div)=count(ancestor::*[ancestor::body])]
    

    输出:id=0,id=1,id=2

    【讨论】:

    • 嗯...如果我想说“这个当前节点”而不是&lt;body&gt;,我会怎么做。所以,从&lt;body&gt; 我会选择 ids 0、1、2,但从第一个 &lt;blockquote&gt; 我会选择 id 3,从第二个,我会选择 id 4。我可以说[ancestor::(the-very-first-element-I-started-from)]吗?
    • XPath 的[ancestor::body] 部分在这里用于从第二个计数步骤的结果中删除body 元素。写[not(name()="body")] 也可以。我不明白你想要达到什么目的。我无法通过“当前节点”(“.”,在 XPath 语言中)或“element-I-started-from”来获得它。我以为你不想选择 id3 和 id4...要从块引用中选择,你为什么不使用://blockquote//p[@id]?如果您可以更详细地描述您确切想要的内容(要提取的元素、XPath 表达式的条件...),那就太好了。
    • 希望我已完全理解您的需求。 body/p|//*[descendant::*[last()][name()="p"]][count(descendant::*)-1=count(descendant::div)]//p 对你有好处吗? xpather.com/gbLfJpdq
    • 这只是选择了所有&lt;p&gt;s,至少在这个例子中(或者链接不适合我)。如果它包含其他内容,它不会选择&lt;p&gt;。也许您将我的要求理解为“包含在来自任何节点的 0 个或多个 &lt;div&gt;s 的链中的任何 &lt;p&gt;”(这确实会选择任何 &lt;p&gt;)。我所追求的是一个表达式,它将选择这样的&lt;div&gt;-contained &lt;p&gt;s 相对于某个任意元素(可能是根元素,或一个特定的&lt;blockquote&gt; 或其他),这个任意元素从跑跑跑。
    • “也许您将我的要求理解为“包含在来自任何节点的 0 个或多个
      的链中的任何

      ”(这确实会选择任何

      )。是的。您可以在我编写的表达式的第一部分声明任意元素。例如,如果/body/blockquote[1] 是您的参考节点:/body/blockquote[1][descendant::*[last()][name()="p"]][count(descendant::*)-1=count(descendant::div)]//p 另一种说法:/body/blockquote[1]//p[count(ancestor::div)=count(/body/blockquote[1]/descendant::*) or count(/body/blockquote[1]/descendant::*)=1]

    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 2016-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多