3

如何在 XPath 中使用递归 AND 条件选择?

例如,给定这个文档:

<root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
  <file name="foo.mp4">
    <chunks>
      <file>
        <chunks>
          <file>
          <chunks>
            <file>1</file>
            <file>2</file>
            <file>3</file>
            <file>4</file>
          </chunks>
          </file>
          <file>
          <chunks>
            <file>5</file>
            <file>6</file>
            <file>7</file>
            <file>8</file>
          </chunks>
          </file>
        </chunks>
      </file>
      <file>
        <chunks>
          <file>
          <chunks>
            <file>9</file>
            <file>10</file>
            <file>11</file>
            <file>12</file>
          </chunks>
          </file>
          <file>
          <chunks>
            <file>13</file>
            <file>14</file>
            <file>15</file>
            <file>16</file>
          </chunks>
          </file>
        </chunks>
      </file>
    </chunks>
  </file>
</root>

我只想选择:

<file>1</file>
<file>2</file>
<file>3</file>
<file>4</file>

所以,实际上是这样的:

//[name="foo.mp4"]/chunks/*[1]/chunks/*[1]/*

但是使用一种通用的方法——即覆盖更深嵌套对象的方法。像这样的东西:

//[name="foo.mp4"]/(chunks/*[1]/)+/*

(cond)+不是 XPath 语法,而是我想要的类似正则表达式的表示。

4

2 回答 2

4

递归意味着自引用,在 XPath 中不能直接使用。忽略中间元素级别的常用方法是通过descendant-or-self轴 ( //),由所需属性锚定。

例如,以下每个 XPath 表达式,

  • file值小于 5 的所有元素:

    //file[number() < 5]
    
  • 前 4 个叶子file元素:

    //file[not(*)][count(preceding::file[not(*)]) < 4]
    
  • file其祖先没有前辈的叶子元素:

    //file[not(*)][not(ancestor::*[preceding::*])]
    

会选择

<file>1</file>
<file>2</file>
<file>3</file>
<file>4</file>

按照要求。

于 2016-02-21T00:08:50.460 回答
2

据我所知,没有递归 XPath 这样的东西。因此,您需要将 XPath 与其他一些东西(如 XSLT 或编程语言)结合起来才能进行递归。使用纯 XPath,如果可能,您需要以不同的方式表述需求。

我不知道这是否适用于您的实际数据,但如果您可以将要求表述为以下内容,例如:

“在其中file[@name='foo.mp4'],找到第一个<chunk>包含叶子 <file>的元素,即<file>不包含任何元素的元素,只有文本节点,并返回叶子 <file>元素”

那么将有一个可能的纯 XPath 解决方案:

(//file[@name='foo.mp4']//chunks[not(file/*)])[1]/file

给定有问题的示例 XML,file上述 XPath 表达式在测试时返回 1 到 4的预期输出here

于 2016-02-21T00:21:34.237 回答