Как я могу использовать XPath для поиска минимального значения атрибута в наборе элементов?
Если у меня есть XML, как:
<foo>
<bar id="1" score="192" />
<bar id="2" score="227" />
<bar id="3" score="105" />
...
</foo>
могу ли я использовать XPath для поиска минимальных и максимальных значений score
?
редактировать инструмент я использую (Андариэль задачи ant) не поддерживает решение XPath 2.0.
6 ответов
вот немного более короткое решение.
максимальный:
/foo/bar/@score[not(. < ../../bar/@score)][1]
минимальные:
/foo/bar/@score[not(. > ../../bar/@score)][1]
я отредактировал предикат так, чтобы он был применим к любой последовательности bar
, даже если вы решили изменить путь. Обратите внимание, что родителем атрибута является элемент, к которому он принадлежит.
если встраивание этих запросов в XML-файлы, такие как XSLT или Ant скрипты, не забудьте кодировать <
и >
as <
уважая >
.
оказывается, инструмент не поддерживает XPath 2.0.
XPath 1.0 не имеет фантазии min()
и max()
функции, поэтому, чтобы найти эти значения, нам нужно быть немного сложным с логикой XPath и сравнить значения на братьях узла:
максимальный:
/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 скрипты, не забудьте кодировать <
и >
as <
уважая >
.
Это должно работать ...
max(foo/bar/@score)
... и...
min(foo/bar/@score)
... проверьте это ссылка на функцию.
я наткнулся на нить и не нашел ответа, который работал для меня, так где же то, что я в конечном итоге использовал...
выводит самое низкое значение, конечно, вы можете выбрать вывод @id из узла с самым низким значением вместо того, чтобы выбирать.
<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>
попробуйте это:
//foo/bar[not(preceding-sibling::bar/@score <= @score) and not(following-sibling::bar/@score <= @score)]
возможно, это будет работать на XPath 1.0.
Я знаю, что это пять лет. Просто добавив еще несколько вариантов для тех, кто может искать и наткнулся на эту.
что-то похожее на это работало для меня в XSLT 2.0.
min(//bar[@score !='']/@score)
на !=''
было избежать нулей, которые воспитывали значения NaN (вероятно, есть лучший способ сделать это)
вот рабочий xpath / xquery:
//bar/@score[@score=min(//*[@score !='']/number(@score))]