Теперь, когда я снова посмотрю на этот вопрос, я думаю, что реальная проблема не в итерации , а в использовании //
.
Это FAQ :
//p[@class='myclass'][1]
выбирает каждый элемент p
, который имеет атрибут class
со значением "myclass"
и является первым таким потомком своего родителя. Поэтому это выражение может выбирать множество элементов p
, ни один из которых на самом деле не является первым таким элементом p
в документе.
Когда мы хотим получить первый p
элемент в документе, который удовлетворяет вышеуказанному предикату, одно правильное выражение:
(//p)[@class='myclass'][1]
Помните : оператор []
имеет более высокий приоритет (приоритет), чем сокращение //
.
Всякий раз, когда вам нужно проиндексировать узлы, выбранные с помощью //
, всегда помещайте выражение для индексации в скобки.
Вот демонстрация :
<nums>
<a>
<n x="1"/>
<n x="2"/>
<n x="3"/>
<n x="4"/>
</a>
<b>
<n x="5"/>
<n x="6"/>
<n x="7"/>
<n x="8"/>
</b>
</nums>
Выражение XPath :
//n[@x mod 2 = 0][1]
выбирает следующие два узла :
<n x="2" />
<n x="6" />
Выражение XPath :
(//n)[@x mod 2 = 0][1]
выбирает точно первый n
элемент в документе со свойством wanted:
<n x="2" />
Попробуйте сначала с помощью следующего преобразования :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select="//n[@x mod 2 = 0][1]"/>
</xsl:template>
</xsl:stylesheet>
и в результате получается два узла .
<n x="2" />
<n x="6" />
Теперь измените выражение XPath, как показано ниже, и попробуйте снова :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select="(//n)[@x mod 2 = 0][1]"/>
</xsl:template>
</xsl:stylesheet>
и в результате мы действительно хотим получить - первый такой элемент n
в документе:
<n x="2" />