これらは、単一のXPath 1.0式で選択することはできません(XPath 1.0には範囲変数がないため)。
考えられる解決策の1つは、すべての要素を選択し、その/*/*/*
要素を使用して各要素の名前を取得し、name()
評価することです/*/*/*[name() = $currentName][2]
(ここで$currentName
、取得した名前に置き換える必要があります。最後の式で要素を選択した場合、はcurrentName
名前です。これは少なくとも2回発生するため、その要素を保持します。すべての要素とその名前を使用して保持します。補助的な手順として、名前(および選択した要素)をハッシュテーブルに配置することで重複させることができます。
Xpath 2.0では、単一のXPath式を使用して、同じ名前の兄弟が少なくとも1人いる、特定の親のすべての子を選択するのは簡単です。
/*/*/*
[name() = following-sibling::*/name()
and
not(name() = preceding-sibling::*/name())
]
はるかにコンパクトな表現:
/*/*/*[index-of(/*/*/*/name(), name())[2]]
XSLT 2.0ベースの検証:
<xsl:stylesheet version="2.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=
"/*/*/*[index-of(/*/*/*/name(), name())[2]]"/>
</xsl:template>
</xsl:stylesheet>
この変換が提供されたXMLドキュメントに適用される場合:
<root>
<parent>
<node>...</node>
<node_unique>...</node_unique>
<node>...</node>
<another_one>...</another_one>
<another_one>...</another_one>
</parent>
</root>
上記のXPath式が評価され、この評価要素から選択されたものが出力にコピーされます。
<node>...</node>
<another_one>...</another_one>
注:関連する質問/回答については、こちらをご覧ください。