outerElement
これは、の任意の数の異なる名前の子とそれらの間の任意の優先順序に対して機能する一般的なソリューションです。
<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:param name="pUncertainElName" select="'second'"/>
<xsl:param name="pOrderedNames" select="'|first|second|third|'"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="outerElement">
<xsl:variable name="vrtfFirstPass">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
<xsl:apply-templates select=
"self::*[not(*[name() = $pUncertainElName])
or
*[name()=$pUncertainElName and @missing-cause]]"
mode="missing"/>
</xsl:copy>
</xsl:variable>
<xsl:apply-templates select="ext:node-set($vrtfFirstPass)/*" mode="pass2"/>
</xsl:template>
<xsl:template match="*[@missing-cause]"/>
<xsl:template match="*" mode="missing">
<xsl:element name="{$pUncertainElName}">
<textElement>Some Text</textElement>
</xsl:element>
</xsl:template>
<xsl:template match="outerElement" mode="pass2">
<xsl:copy>
<xsl:apply-templates>
<xsl:sort data-type="number" select=
"string-length(substring-before($pOrderedNames,
concat('|', name(), '|')
)
)"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
この変換が次のXMLドキュメントに適用される場合:
<doc>
<outerElement>
<first>
<textElement>Some Text</textElement>
</first>
<second missing-cause="">
<textElement>Some Text</textElement>
</second>
<third>
<textElement>Some Text</textElement>
</third>
</outerElement>
</doc>
必要な正しい結果が生成されます。
<doc>
<outerElement>
<first>
<textElement>Some Text</textElement>
</first>
<second>
<textElement>Some Text</textElement>
</second>
<third>
<textElement>Some Text</textElement>
</third>
</outerElement>
</doc>
このXMLドキュメントに適用される場合:
<doc>
<outerElement>
<first>
<textElement>Some Text</textElement>
</first>
<third>
<textElement>Some Text</textElement>
</third>
</outerElement>
</doc>
再び、必要な正しい結果が生成されます:
<doc>
<outerElement>
<first>
<textElement>Some Text</textElement>
</first>
<second>
<textElement>Some Text</textElement>
</second>
<third>
<textElement>Some Text</textElement>
</third>
</outerElement>
</doc>
最後に、同じ変換がこのXMLドキュメントに適用される場合:
<doc>
<outerElement>
<first>
<textElement>Some Text</textElement>
</first>
<second>
<textElement>Some Text</textElement>
</second>
<third>
<textElement>Some Text</textElement>
</third>
</outerElement>
</doc>
ここでも、同じように、正しい結果が生成されます。
<doc>
<outerElement>
<first>
<textElement>Some Text</textElement>
</first>
<second>
<textElement>Some Text</textElement>
</second>
<third>
<textElement>Some Text</textElement>
</third>
</outerElement>
</doc>
注:
異なる名前の子outerElement
(3つだけではない)は無制限に存在する可能性があり、それらの順序は事前にわからない場合があります。
例:
このXMLドキュメントを考えると:
<doc>
<outerElement>
<first>
<textElement>Some Text</textElement>
</first>
<second missing-cause="">
<textElement>Some Text</textElement>
</second>
<third>
<textElement>Some Text</textElement>
</third>
<fourth>
<textElement>Some Text</textElement>
</fourth>
</outerElement>
</doc>
そしてこの順序:4番目、2番目、3番目、1番目
交換するだけです:
<xsl:param name="pOrderedNames" select="'|first|second|third|'"/>
と:
<xsl:param name="pOrderedNames" select="'|fourth|second|third|first|'"/>
そして今、新しい望みの結果が生成されます:
<doc>
<outerElement>
<fourth>
<textElement>Some Text</textElement>
</fourth>
<second>
<textElement>Some Text</textElement>
</second>
<third>
<textElement>Some Text</textElement>
</third>
<first>
<textElement>Some Text</textElement>
</first>
</outerElement>
</doc>
説明:
これは2パス変換です。
存在する場合と存在しない場合がある要素の名前は、external/globalパラメーターで指定されます$pUncertainElName
。この説明の便宜上、この要素を。と呼びsecond
ます。
最初のパスでは、属性を持つものouterElement
を除いて、のすべての子が「そのまま」コピーされます。要素が存在しないか、属性を持っている場合は、正確に必要な要素の新しい子を出力します。second
missing-cause
second
missing-cause
outerElement
second
2番目のパスでは、最初のパスで生成された子を、名前がouterElement
付けられた別の外部/グローバルパラメーターで指定された優先度に従って並べ替えます$pOrderedNames
(この文字列で別の名前が残っている名前の方が優先度が高くなります)