Xpath для фильтрации xml по значениям нескольких узлов

#xml #xpath

#xml #xpath

Вопрос:

У меня есть следующий xml:

 <?xml version="1.0" encoding="UTF-8"?>
<Library>
   <Aisle>
      <Shelf>
         <Genre>Physics</Genre>
         <sequenceNumber>0</sequenceNumber>
         <correctionNumber>0</correctionNumber>
      </Shelf>
   </Aisle>
   <Aisle>
      <Shelf>
         <Genre>Math</Genre>
         <sequenceNumber>1</sequenceNumber>
         <correctionNumber>0</correctionNumber>
      </Shelf>
   </Aisle>
   <Aisle>
      <Shelf>
         <Genre>Applied Math</Genre>
         <sequenceNumber>1</sequenceNumber>
         <correctionNumber>1</correctionNumber>
      </Shelf>
   </Aisle>
   <Aisle>
      <Shelf>
         <Genre>Chemistry</Genre>
         <sequenceNumber>2</sequenceNumber>
         <correctionNumber>0</correctionNumber>
      </Shelf>
   </Aisle>
   <Aisle>
      <Shelf>
         <Genre>Organic Chemistry</Genre>
         <sequenceNumber>2</sequenceNumber>
         <correctionNumber>1</correctionNumber>
      </Shelf>
   </Aisle>
   <Aisle>
      <Shelf>
         <Genre>Inorganic Chemistry</Genre>
         <sequenceNumber>2</sequenceNumber>
         <correctionNumber>2</correctionNumber>
      </Shelf>
   </Aisle>
</Library>
 

в котором я должен возвращать (только) проходы, у которых correctionNumber равен max(correctionNumber), учитывая тот же SequenceNumber.
Итак, в этом примере мне пришлось бы вернуть следующий результат:

    <Aisle>
      <Shelf>
         <Genre>Physics</Genre>
         <sequenceNumber>0</sequenceNumber>
         <correctionNumber>0</correctionNumber>
      </Shelf>
   </Aisle>
   <Aisle>
      <Shelf>
         <Genre>Applied Math</Genre>
         <sequenceNumber>1</sequenceNumber>
         <correctionNumber>1</correctionNumber>
      </Shelf>
   </Aisle>
   <Aisle>
      <Shelf>
         <Genre>Inorganic Chemistry</Genre>
         <sequenceNumber>2</sequenceNumber>
         <correctionNumber>2</correctionNumber>
      </Shelf>
   </Aisle>
 

Я тестирую xpath на https://www.freeformatter.com/xpath-tester.html .
Моя первоначальная идея заключалась в использовании choose() функции, описанной на https://developer.mozilla.org/en-US/docs/Web/XPath/Functions/choose , поэтому я мог бы проверить, меньше ли значение max() , но, похоже choose , функция недействительна.
Кто-нибудь знает xpath, который мог бы оценивать максимальное значение внутри него, возвращая только нужные узлы?

Комментарии:

1. Неясно, где вы ищете какой-либо «максимум»; у каждого <Aisle> есть только один <Shelf> дочерний узел, который, в свою очередь, имеет только один <correctionNumber> дочерний узел. Итак, из чего рассчитывается максимальное значение?

Ответ №1:

Поскольку вы запрашиваете структуру Group by / Having, вам, вероятно, потребуется использовать процессор XPath с поддержкой XQuery 3:

 for $s in /Library/Aisle/Shelf
group by $seqNo := $s/sequenceNumber
return    $seqNo || ": " || max($s/correctionNumber) || " " || $s/Genre
 

Который дает нам ожидаемые столбцы (используя пользовательский вывод):

 0: 0 Physics
1: 1 Math
2: 2 Chemistry
 

<a rel=»noreferrer noopener nofollow» href=»https:///videlibri.sourceforge.net/cgi-bin/xidelcgi?amp;data=

Physics
0
0

Math
1
0

Applied Math
1
1

Chemistry
2
0

Organic Chemistry
2
1

Inorganic Chemistry
2
2

amp;=Genreamp;extract=for $s in /Library/Aisle/Shelf
group by $seqNo := $s/sequenceNumber
return $seqNo || «: » || max($s/correctionNumber) || » » || $s/Genreamp;=for $s in /Library/Aisle/Shelf
group by $seqNo := $s/sequenceNumber
return $seqNo || «: » || max($s/correctionNumber) || » » || $s/Genreamp;input-format=xmlamp;printed-node-format=textamp;output-format=adhocamp;compatibility=Enable all extensionsamp;dot-notation=unambiguousamp;extract-kind=xquery3.0″ rel=»nofollow noreferrer»>Онлайн-демонстрация