递归XPath的条件

时间:2016-02-20 23:49:46

标签: xml xpath recursive-regex

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

例如,鉴于此文件:

Tickable

我想选择:

<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]/)+/* 不是XPath语法,而是类似于我想要的正则表达式。

2 个答案:

答案 0 :(得分:1)

递归意味着自引用,并且在XPath中不能直接使用。忽略干预元素级别的常用方法是通过descendant-or-self轴(//),以期望的属性为基础。

例如,以下每个XPath表达式

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

    //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>
根据要求

答案 1 :(得分:1)

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

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

  

&#34;在file[@name='foo.mp4']内,找到包含 leaf <chunk>的第一个<file>,即不包含<file>元素39; t包含任何元素,仅包含文本节点,并返回 leaf <file>元素&#34;

然后会有一个可能的纯XPath解决方案:

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

给出了相关的示例XML,在测试here时,上述XPath表达式返回file 1到4的预期输出。