Cette feuille de style, appliqué à votre échantillon d'entrée:
<!-- 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" />
retours
<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>
Remarque
- L'utilisation de modes de modèle. J'ai fait un modèle spécifiquement pour le groupement
Customer
. Le traitement des noeuds normaux se produit dans le modèle d'identité.
- L'utilisation d'une boucle à un seul nœud
xsl:for-each
pour modifier le nœud de contexte pour xsl:copy
.
- L'utilisation d'un modèle vide pour supprimer des nœuds de la sortie.
- Que vous pouvez copier des attributs avec
xsl:copy
et encore écraser l'un d'entre eux plus tard.
- La sortie est dans l'ordre des documents.
Pour forcer un ordre particulier, utiliser quelque chose comme ceci:
<xsl:apply-templates select="//Customer" mode="CustomerGroup">
<xsl:sort select="../@Code" data-type="text" order="ascending" />
</xsl:apply-templates>
et
<xsl:apply-templates select="key('kCustomerGroup', $officeCode)">
<xsl:sort select="@CodeModifier" data-type="number" order="ascending" />
</xsl:apply-templates>
Bonne question, +1. Voir ma réponse pour une solution XSLT 2.0 complète, très courte et facile. :) –