使用:
.//element[(ancestor::main|ancestor::element)[last()][self::main]]
XSLT を使用した簡単な検証を次に示します。
<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:for-each select=
".//element
[(ancestor::main|ancestor::element)
[last()][self::main]
]">
<xsl:copy-of select="."/>
==================
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
この変換が提供された XML ドキュメントに適用されると、次のようになります。
<main>
<sub1>
<element>
<sub2>
<element>
<sub3/>
</element>
</sub2>
</element>
</sub1>
<sub4>
<sub5>
<element>
<sub6>
<element>
<sub7/>
</element>
</sub6>
</element>
</sub5>
</sub4>
<sub8>
<element/>
</sub8>
</main>
Xpath 式は、現在のノードをドキュメントの最上位ノードとして評価され、この評価の結果は、便利な区切り文字列を使用して出力にコピーされます。
<element>
<sub2>
<element>
<sub3/>
</element>
</sub2>
</element>
==================
<element>
<sub6>
<element>
<sub7/>
</element>
</sub6>
</element>
==================
<element/>
==================
説明:
表現:
.//element
[(ancestor::main|ancestor::element)
[last()]
[self::main]
]
現在のノードのすべての子孫element
要素を選択し、2 つの可能な祖先 (上向き)main
またはelement
isの最初のものを選択しますmain
。
つまりelement
、selected の祖先であり、祖先のelement
前に (上に向かって) 発生する はありませんmain
。
last()
が だけでなく述語として使用される理由を理解する[1]
には、2 つの先祖の中で最も近いものが文書順で最後であることを覚えておく必要があります。
注意してください:
この XPath 式は、現在のノード自体が先祖element
を持つ場合でも、必要なすべての要素を正しく選択します。element
Ian Roberts による回答で提案されたような表現:
.//element[not(ancestor::element)]
この場合、何も選択しません。
更新:
Michael Kay が指摘したように、この問題をさらに一般化し、他のmain
要素をドキュメントのどこにでも表示できるようにすると、この回答で提案されている表現は「誤検知」を選択する可能性があります。
current()
以下は、この状況でも正しいカウントを生成する更新された式 (XSLT 関数を使用するため、純粋な/スタンドアロンの XPath 式ではなくなりました)です。
.//element
[(ancestor::main|ancestor::element)
[last()][self::main]
and
count(current()|ancestor::main[1]) = 1
]"/>