Теперь, когда я снова смотрю на этот вопрос, я думаю, что настоящая проблема не в итерации, а в использовании //
.
Это часто задаваемые вопросы:
//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
элемент в документе с требуемым свойством:
<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" />
person
Dimitre Novatchev
schedule
15.09.2010