Как я могу использовать 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 &lt; уважая &gt;.


оказывается, инструмент не поддерживает 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 &lt; уважая &gt;.


Это должно работать ...

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))]