2010-07-30 6 views
1

Je dois fusionner certains nœuds xml en fonction d'une valeur d'attribut, modifier cette valeur d'attribut sur le nœud fusionné et additionner un autre attribut.besoin de fusionner des nœuds xml basés sur une valeur d'attribut

Je suis en mesure de modifier la valeur des attributs, mais je ne pouvais pas comprendre comment somme (@count) et l'affecter à @count sur le xml résultant

Source xml

<xml> 
<books category="X" count="2"> 
    <book name="bookx1"/> 
    <book name="bookx2"/> 
</books> 
<books category="Y" count="3"> 
    <book name="booky1"/> 
    <book name="booky2"/> 
    <book name="booky3"/> 
</books> 
<books category="Z" count="2"> 
    <book name="bookz1"/> 
    <book name="bookz2"/> 
</books></xml> 

Après xslt transform il a besoin d'être comme ça

<xml> 
<books category="A" count="5"> 
    <book name="bookx1"/> 
    <book name="bookx2"/> 
    <book name="booky1"/> 
    <book name="booky2"/> 
    <book name="booky3"/> 
</books> 
<books category="Z" count="2"> 
    <book name="bookz1"/> 
    <book name="bookz2"/> 
</books></xml> 

Ceci est mon xslt partielle

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml"/> 
<xsl:template match="*"> 
    <xsl:element name="{local-name()}"> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:element> 
</xsl:template> 
<xsl:template match="@*"> 
    <xsl:copy-of select="."/> 
</xsl:template> 

<xsl:template match="@category"> 
    <xsl:attribute name="category"> 
    <xsl:choose> 
    <xsl:when test=".='X'"> 
    <xsl:text>A</xsl:text> 
    </xsl:when> 
    <xsl:when test=".='Y'"> 
    <xsl:text>A</xsl:text> 
    </xsl:when> 
    <xsl:when test=".='Z'"> 
    <xsl:text>B</xsl:text> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:value-of select="."/> 
    </xsl:otherwise> 
    </xsl:choose> 
    </xsl:attribute> 
</xsl:template> 

<xsl:template match="books[@category='X']"/> 
<xsl:template match="books[@category='Y']"/></xsl:transform> 
+0

Veillez à mettre en retrait tout le bloc de code, pas seulement la première ligne. –

+0

Bonne question (+1). Voir ma réponse pour une solution courte et simple. :) –

Répondre

1

Cette transformation:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="kBooksByCat" match="books" 
    use="@category = 'Z'"/> 

<xsl:template match="node()|@*" name="identity"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="/*"> 
    <xml> 
    <xsl:variable name="vNonZ" 
     select="key('kBooksByCat', 'false')"/> 

    <xsl:variable name="vCatZ" 
     select="key('kBooksByCat', 'true')"/> 

    <xsl:if test="$vNonZ"> 
    <books category="A" count="{sum($vNonZ/@count)}"> 
     <xsl:apply-templates select="$vNonZ/node()"/> 
    </books> 
    </xsl:if> 
    <xsl:if test="$vCatZ"> 
    <books category="B" count="{sum($vCatZ/@count)}"> 
     <xsl:apply-templates select="$vCatZ/node()"/> 
    </books> 
    </xsl:if> 
    </xml> 
</xsl:template> 
</xsl:stylesheet> 

lorsqu'il est appliqué sur le document XML fourni:

<xml> 
<books category="X" count="2"> 
    <book name="bookx1"/> 
    <book name="bookx2"/> 
</books> 
<books category="Y" count="3"> 
    <book name="booky1"/> 
    <book name="booky2"/> 
    <book name="booky3"/> 
</books> 
<books category="Z" count="2"> 
    <book name="bookz1"/> 
    <book name="bookz2"/> 
</books> 
</xml> 

produit le résultat souhaité, correct:

<xml> 
    <books category="A" count="5"> 
     <book name="bookx1"/> 
     <book name="bookx2"/> 
     <book name="booky1"/> 
     <book name="booky2"/> 
     <book name="booky3"/> 
    </books> 
    <books category="B" count="2"> 
     <book name="bookz1"/> 
     <book name="bookz2"/> 
    </books> 
</xml> 
+0

Wow, génial! c'est exactement ce dont j'avais besoin. Merci beaucoup – gangt

+0

@gangt: Heureuse ma réponse a été utile. En SO, la gratitude est exprimée en acceptant la bonne réponse et/ou en augmentant les réponses utiles. –

0

Une autre feuille de style sans clé:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="books[@category='Z'][1]"> 
     <xsl:variable name="us" select="../books[@category='Z']"/> 
     <books category="B" count="{sum($us/@count)}"> 
      <xsl:apply-templates select="$us/node()"/> 
     </books> 
    </xsl:template> 
    <xsl:template match="books[@category!='Z'][1]"> 
     <xsl:variable name="us" select="../books[@category!='Z']"/> 
     <books category="A" count="{sum($us/@count)}"> 
      <xsl:apply-templates select="$us/node()"/> 
     </books> 
    </xsl:template> 
    <xsl:template match="books"/> 
</xsl:stylesheet> 

Sortie:

<xml> 
    <books category="A" count="5"> 
     <book name="bookx1"></book> 
     <book name="bookx2"></book> 
     <book name="booky1"></book> 
     <book name="booky2"></book> 
     <book name="booky3"></book> 
    </books> 
    <books category="B" count="2"> 
     <book name="bookz1"></book> 
     <book name="bookz2"></book> 
    </books> 
</xml> 

Remarque: Juste pour le plaisir. Les deux modèles de livres sont si proches. Peut-être existe-t-il un moyen d'exprimer ceux-ci dans un modèle. Certains complexe translate?

+0

Merci à vous deux. Les deux xslt fonctionnent comme un charme – gangt

Questions connexes