Как решение XPath 2.0, так и принятый в настоящее время ответ очень неэффективны (O (N ^ 2)).
Это решение имеет сублинейную сложность:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kElemsByName" match="/*/*"
use="name()"/>
<xsl:template match="/">
<xsl:copy-of select=
"/*/*[generate-id()
=
generate-id(key('kElemsByName', name())[last()])
]"/>
</xsl:template>
</xsl:stylesheet>
при применении к предоставленному документу XML :
<root>
<a>One</a>
<a>Two</a>
<b>Three</b>
<c>Four</c>
<a>Five</a>
<b>
<a>Six</a>
</b>
</root>
желаемый, правильный результат получается :
<c>Four</c>
<a>Five</a>
<b>
<a>Six</a>
</b>
Объяснение : Это модифицированный вариант мюнхенской группировки - так, чтобы не первым. но последний узел в каждой группе обрабатывается.
II XPath 2.0 однострочный :
Использование:
/*/*[index-of(/*/*/name(), name())[last()]]
Проверка с использованием XSLT 2.0 в качестве хоста XPath 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:sequence select=
"/*/*[index-of(/*/*/name(), name())[last()]]"/>
</xsl:template>
</xsl:stylesheet>
Когда это преобразование применяется к тому же документу XML (предоставленному ранее), получается тот же правильный результат :
<c>Four</c>
<a>Five</a>
<b>
<a>Six</a>
</b>