Вот общее решение, которое работает с любым узлом, принадлежащим любому набору узлов в том же документе:
Я использую XSLT для реализации решения, но в итоге получаю одно выражение XPath, которое можно использовать с любым другим языком хостинга.
Пусть $vNodeSet
будет набором узлов, а $vNode
будет узлом в этом наборе узлов, положение которого мы хотим найти.
Затем пусть $vPrecNodes
содержит все узлы в документе XML, предшествующие $vNode
.
Затем пусть $vAncNodes
содержит все узлы в документе XML, которые являются предками $vNode
.
Набор узлов в $vNodeSet
, который предшествует $vNode
в порядке документа, состоит из всех узлов в наборе узлов, которые также принадлежат $vPrecNodes
, и всех узлов в наборе узлов, которые также принадлежат $vAncNodes
.
Я буду использовать известную формулу Кайсиана для пересечения двух наборов узлов:
$ns1[count(.|$ns2) = count($ns2)]
содержит точно узлы на пересечении $ns1
с $ns2
.
Исходя из всего этого, пусть $vPrecInNodeSet
- это набор узлов в $vNodeSet
, которые предшествуют $vNode
в порядке документа. Следующее выражение XPath определяет $vPrecInNodeSet
:
$vNodeSet
[count(.|$vPrecNodes) = count($vPrecNodes)
or
count(.|$vAncNodes) = count($vAncNodes)
]
Наконец, желаемая позиция: count($vPrecInNodeSet) +1
Вот как все это работает вместе:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="vNodeSet" select="/*/a/b"/>
<xsl:variable name="vNode" select="$vNodeSet[. = 'tsr'][1]"/>
<xsl:variable name="vPrecNodes" select="$vNode/preceding::node()"/>
<xsl:variable name="vAncNodes" select="$vNode/ancestor::node()"/>
<xsl:variable name="vPrecInNodeSet" select=
"$vNodeSet
[count(.|$vPrecNodes) = count($vPrecNodes)
or
count(.|$vAncNodes) = count($vAncNodes)
]
"/>
<xsl:template match="/">
<xsl:value-of select="count($vPrecInNodeSet) +1"/>
</xsl:template>
</xsl:stylesheet>
Когда вышеуказанное преобразование применяется к предоставленному XML-документу:
<root>
<a>
<b>zyx</b>
</a>
<a>
<b>wvu</b>
</a>
<a>
<b>tsr</b>
</a>
<a>
<b>qpo</b>
</a>
</root>
будет получен правильный результат:
3
Обратите внимание: это решение не зависит от XSLT (используется только в иллюстративных целях). Вы можете собрать одно выражение XPath, заменяя переменные их определением, пока не останется больше переменных для замены.
person
Dimitre Novatchev
schedule
25.08.2010