この変換:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kChildren" match="thing" use="parent/@name"/>
<xsl:template match="/*">
<xsl:variable name="vrtfPass1">
<things>
<xsl:apply-templates select="thing[not(parent)]"/>
</things>
</xsl:variable>
<xsl:apply-templates select="ext:node-set($vrtfPass1)/*"
mode="pass2"/>
</xsl:template>
<xsl:template match="thing">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="key('kChildren', @name)"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()|@*" mode="pass2">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="pass2"/>
</xsl:copy>
</xsl:template>
<xsl:template mode="pass2"
match="*[not(@name = 'Waldo' or .//*[@name='Waldo'])]" />
</xsl:stylesheet>
提供されたXMLドキュメントに適用した場合:
<things>
<thing name="Foo" available="yes"/>
<thing name="Bar" available="no"/>
<thing name="Baz" available="yes">
<parent name="Foo"/>
<parent name="Bar"/>
</thing>
<thing name="Qux" available="no">
<parent name="Foo"/>
<parent name="Bar"/>
</thing>
<thing name="Waldo" available="yes">
<parent name="Foo"/>
<parent name="Bar"/>
<parent name="Qux"/>
</thing>
</things>
「waldo」を含む「branchs」のみを含む結果を生成します。
<things>
<thing name="Foo" available="yes">
<thing name="Qux" available="no">
<thing name="Waldo" available="yes"/>
</thing>
<thing name="Waldo" available="yes"/>
</thing>
<thing name="Bar" available="no">
<thing name="Qux" available="no">
<thing name="Waldo" available="yes"/>
</thing>
<thing name="Waldo" available="yes"/>
</thing>
</things>
これを最終的なHTML形式に変換することは、読者の練習問題として残されています。
説明:
これは2パス変換です。
最初のパスは、親子関係が明示的に表現されるツリーを構築します。
2番目のパスはIDルールであり、string-valueのthing
with属性を含まないサブツリーの場合は、本文が空のテンプレート(「削除」テンプレート)でオーバーレイされます。name
"Waldo"
最初のパスの結果は次のとおりです。
<things>
<thing name="Foo" available="yes">
<thing name="Baz" available="yes"/>
<thing name="Qux" available="no">
<thing name="Waldo" available="yes"/>
</thing>
<thing name="Waldo" available="yes"/>
</thing>
<thing name="Bar" available="no">
<thing name="Baz" available="yes"/>
<thing name="Qux" available="no">
<thing name="Waldo" available="yes"/>
</thing>
<thing name="Waldo" available="yes"/>
</thing>
</things>
2番目のパスは、2つの<thing name="Baz" available="yes"/>
要素を取り除き、最終結果を生成します。