这个样式表,适用于您的输入样本:
<!-- a key to group Customers by their office code + modifier -->
<xsl:key name="kCustomerGroup" match="Customer"
use="concat(../@Code, @CodeModifier)"
/>
<!-- identity template: copies everything that is not handled otherwise -->
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<!-- apply templates directly to customers. modify as necessary -->
<xsl:template match="/">
<xsl:apply-templates select="//Customer" mode="CustomerGroup" />
</xsl:template>
<xsl:template match="Customer" mode="CustomerGroup">
<xsl:variable name="officeCode" select="concat(../@Code, @CodeModifier)" />
<!-- if this Customer is first of his respective group... -->
<xsl:if test="
generate-id()
=
generate-id(key('kCustomerGroup', $officeCode)[1])
">
<!-- use for-each to switch the context node to the parent -->
<xsl:for-each select="..">
<xsl:copy>
<xsl:apply-templates select="@*" />
<!-- overwrite the @Code attribute -->
<xsl:attribute name="Code">
<xsl:value-of select="$officeCode" />
</xsl:attribute>
<!-- now handle the Customer group members -->
<xsl:apply-templates select="key('kCustomerGroup', $officeCode)" />
</xsl:copy>
</xsl:for-each>
</xsl:if>
</xsl:template>
<!-- remove unwanted attribute with empty template -->
<xsl:template match="Customer/@CodeModifier" />
回报
<Office Code="1A" OtherAttribute="5">
<Customer CustomerId="0010"></Customer>
</Office>
<Office Code="1B" OtherAttribute="5">
<Customer CustomerId="0011"></Customer>
<Customer CustomerId="0012"></Customer>
</Office>
<Office Code="2A" OtherAttribute="6">
<Customer CustomerId="2010"></Customer>
</Office>
<Office Code="2C" OtherAttribute="6">
<Customer CustomerId="0011"></Customer>
</Office>
注
- 使用的模板模式。我专门为
Customer
分组制作了一个模板。正常节点处理发生在身份模板中。
- 使用单节点
xsl:for-each
循环更改xsl:copy
的上下文节点。
- 使用空模板从输出中删除节点。
- 你可以用
xsl:copy
和复制属性,以后覆盖其中的一个。
- 输出按文档顺序排列。
要强制特定的顺序,使用这样的:
<xsl:apply-templates select="//Customer" mode="CustomerGroup">
<xsl:sort select="../@Code" data-type="text" order="ascending" />
</xsl:apply-templates>
和
<xsl:apply-templates select="key('kCustomerGroup', $officeCode)">
<xsl:sort select="@CodeModifier" data-type="number" order="ascending" />
</xsl:apply-templates>
问得好,+1。查看我的答案,获取完整,非常简短的XSLT 2.0解决方案。 :) – 2011-06-06 13:36:54