XPath: получить все между двумя пустыми узлами - PullRequest
0 голосов
/ 23 мая 2018

Мне нужно написать выражение xpath, чтобы получить все (узлы и текст) между пустым узлом ( pb ) и следующим вхождением pb .

Я могу получить «все» после узла pb до конца XML-файла с этим запросом:

 //pb/following::*|//pb/following::text()

Но я хочу сгруппировать «одиночные» результаты по pb до следующегоpb.

Пример:

...
<pb/>
<elementX>text here </elementX>     --|
<moreElements/>                       |    Group 1
Plain text here without element     --|
<pb/>
<elementY>text here </elementY>     --|    Group 2
...                                 --|
<pb/>
...                                 --|    Group 3
EOF                                 --|

Так что я хочу все между 2 pb и сгруппировать его.Для этого примера должно быть 3 группы результатов.Все элементы от первого pb до второго должны быть в 1-й группе.Со второй pb до третьей pb - вторая группа.И от третьего pb до конца должна быть третья группа.

Трудно описать словами.Нужна дополнительная информация?

Как указать xpath, где заканчивать и сгруппировать результаты?

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Как указывает Кристиан, XPath может доставлять только набор узлов (или последовательность узлов), поэтому нет никакой возможности группировать.Также сложно (но не невозможно) доставить узлы между двумя веховыми тегами <start/> и <end/>.В XPath 1.0 вы можете сделать:

start/following-sibling::node()[following-sibling::end]

, но это, вероятно, будет очень неэффективно с длинной входной последовательностью.Решения, использующие окна XQuery или группировку XSLT, являются гораздо более удовлетворительными.

0 голосов
/ 23 мая 2018

Если вы хотите создать группы, XPath не будет достаточно (потому что результат всегда будет плоской последовательностью).Решение XQuery 1.0 выглядит следующим образом:

for $pb in //pb
let $next-pb := $pb/following-sibling::pb[1]
return element group {
  $pb/following-sibling::node()[empty($next-pb) or . << $next-pb]
}

Если ваш процессор поддерживает XQuery 3.0, вы можете использовать более эффективное предложение окна:

declare context item := document {
  <xml>
    <pb/>
    <elementX>text here </elementX>
    <moreElements/>
    Plain text here without element
    <pb/>
    <elementY>text here </elementY>
    ...
    <pb/>
    x
  </xml>
};
for tumbling window $w in /xml/node()
    start $s when name($s) = 'pb'
    end $e when name(head($e/following-sibling::node())) = 'pb'
return element group { tail($w) }
...