次のような入力を想定します。
<gizmo>
<isProduct>True</isProduct>
<isFoo>False</isFoo>
<isBar>True</isBar>
</gizmo>
一般的なアプローチは次のとおりです。
<xsl:template match="gizmo">
<xsl:copy>
<xsl:apply-templates select="*" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[substring(local-name(), 1, 2) = 'is']">
<Type>
<xsl:if test=". = 'True'">
<xsl:value-of select="substring-after(local-name(), 'is')" />
</xsl:if>
</Type>
</xsl:template>
生成するもの:
<gizmo>
<Type>Product</Type>
<Type />
<Type>Bar</Type>
</gizmo>
さらに一般化されたアプローチでは、(大幅に)変更されたID変換を使用します。
<!-- the identity template... well, sort of -->
<xsl:template match="node() | @*">
<xsl:copy>
<!-- all element-type children that begin with 'is' -->
<xsl:variable name="typeNodes" select="
*[substring(local-name(), 1, 2) = 'is']
" />
<!-- all other children (incl. elements that don't begin with 'this ' -->
<xsl:variable name="otherNodes" select="
@* | node()[not(self::*) or self::*[substring(local-name(), 1, 2) != 'is']]
" />
<!-- identity transform all the "other" nodes -->
<xsl:apply-templates select="$otherNodes" />
<!-- collapse all the "type" nodes into a string -->
<xsl:if test="$typeNodes">
<Type>
<xsl:variable name="typeString">
<xsl:apply-templates select="$typeNodes" />
</xsl:variable>
<xsl:value-of select="substring-after($typeString, '-')" />
</Type>
</xsl:if>
</xsl:copy>
</xsl:template>
<!-- this collapses all the "type" nodes into a string -->
<xsl:template match="*[substring(local-name(), 1, 2) = 'is']">
<xsl:if test=". = 'True'">
<xsl:text>-</xsl:text>
<xsl:value-of select="substring-after(local-name(), 'is')" />
</xsl:if>
</xsl:template>
<!-- prevent the output of empty text nodes -->
<xsl:template match="text()">
<xsl:if test="normalize-space() != ''">
<xsl:value-of select="." />
</xsl:if>
</xsl:template>
上記は、XML入力をすべて受け取り、同じ構造を出力します。名前が付けられた要素のみが、ダッシュで区切られた文字列として<is*>
単一のノードに折りたたまれます。<Type>
<!-- in -->
<foo>
<fancyNode />
<gizmo>
<isProduct>True</isProduct>
<isFoo>False</isFoo>
<isBar>True</isBar>
</gizmo>
</foo>
<!-- out -->
<foo>
<fancyNode />
<gizmo>
<Type>Product-Bar</Type>
</gizmo>
</foo>