Как я могу использовать XPath для поиска минимального значения атрибута в наборе элементов?
Если у меня есть XML:
<foo>
<bar id="1" score="192" />
<bar id="2" score="227" />
<bar id="3" score="105" />
...
</foo>
Можно ли использовать XPath для поиска минимального и максимального значений score
?
Изменить: инструмент, который я использую (Andariel ant задачи) не поддерживает решение XPath 2.0.
Ответы
Ответ 1
Оказывается, инструмент не поддерживает XPath 2.0.
XPath 1.0 не имеет функций min()
и max()
, поэтому, чтобы найти эти значения, нам нужно немного сложнее с логикой XPath и сравнить значения для братьев и сестер node:
Максимум:
/foo/bar[not(preceding-sibling::bar/@score >= @score)
and not(following-sibling::bar/@score > @score)]/@score
Минимум:
/foo/bar[not(preceding-sibling::bar/@score <= @score)
and not(following-sibling::bar/@score < @score)]/@score
Если вы вставляете эти запросы в файлы XML, такие как скрипты XSLT или ant, не забудьте закодировать <
и >
как <
соблюдая >
.
Ответ 2
Здесь немного более короткое решение.
Максимум:
/foo/bar/@score[not(. < ../../bar/@score)][1]
Минимум:
/foo/bar/@score[not(. > ../../bar/@score)][1]
Я отредактировал предикат так, чтобы он применим к любой последовательности bar
, даже если вы решили изменить путь. Обратите внимание, что родительский атрибут - это элемент, к которому он принадлежит.
Если вы вставляете эти запросы в файлы XML, такие как скрипты XSLT или ant, не забудьте закодировать <
и >
как <
в отношении >
.
Ответ 3
Это должно работать...
max(foo/bar/@score)
... и...
min(foo/bar/@score)
... проверьте эту ссылку .
Ответ 4
Я наткнулся на нить и не нашел ответа, который сработал у меня, поэтому где же я в конечном итоге использовал...
Выводит самое низкое значение, конечно, вы можете выбрать вывод @id из node с наименьшим значением, а не выбором.
<xsl:for-each select="/foo">
<xsl:sort select="@score"/>
<xsl:if test="position()=1">
<xsl:value-of select="@score"/>
</xsl:if>
</xsl:for-each>
То же самое для максимального значения:
<xsl:for-each select="/foo">
<xsl:sort select="@score" order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of select="@score"/>
</xsl:if>
</xsl:for-each>
Ответ 5
Попробуйте следующее:
//foo/bar[not(preceding-sibling::bar/@score <= @score) and not(following-sibling::bar/@score <= @score)]
Возможно, это будет работать на XPath 1.0.
Ответ 6
Я знаю, что это пять лет. Просто добавьте еще несколько опций для тех, кто может найти и найти это.
Нечто похожее на это сработало для меня в XSLT 2.0.
min(//bar[@score !='']/@score)
!=''
должен был избегать нулей, которые приводили значения NaN (возможно, лучший способ сделать это)
Вот рабочий xpath/xquery:
//bar/@score[@score=min(//*[@score !='']/number(@score))]