假设这样的输入:
<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>
更通用的方法使用(大量)修改的身份转换:
<!-- 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>