2016-02-20 3 views
1

Как использовать рекурсивный И условный выбор в XPath?Условия на рекурсивные XPath

Например, если этот документ:

<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 синтаксис, и регулярное выражение, как представление о том, что я хочу.

+2

Извините, но это очень плохое требование . Вы эффективно говорите «если вход 17, тогда я хочу, чтобы ответ был 23, но я хочу, чтобы это обобщалось для работы с любым вводом». Вы должны дать нам общее правило для вычисления выхода из ввода; мы не можем сделать это из одного примера. –

ответ

1

Рекурсия подразумевает самосознание и недоступна непосредственно в 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> 

по запросу.

1

Нет такой вещи, как рекурсивный XPath, насколько я знаю. Поэтому вам нужно объединить XPath с другими вещами, такими как XSLT или язык программирования, чтобы иметь возможность делать рекурсию. Используя чистый XPath, вам нужно будет сформулировать требование по-разному, если это возможно.

Я не знаю, если это применимо к вашим фактическим данным, но если вы можете сформулировать требование к чему-то вроде следующего, например:

«в file[@name='foo.mp4'], найти первый <chunk> что содержит лист<file> i.е <file> элемент, который не содержит какого-либо элемента, только текстовые узлы, и вернуть лист<file> элементы»

тогда будет возможным чистый раствор XPath:

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

данный образец XML, ожидаемый выход file от 1 до 4 возвращается вышеупомянутым выражением XPath при тестировании here.

Смежные вопросы