2009-11-12 6 views
1

J'essaye de faire la somme du champ qty de mon xml en utilisant xslt 2.0 et de sortir la quantité d'un de mes équipements avec plusieurs entrées sans sommation par le groupe d'équipement. Des idées sur la façon dont cela peut être réparé?Addition d'une quantité en utilisant XSLT 2.0 avec le regroupement

C'est le XSLT J'utilise:

<xsl:for-each-group select="//node()" group-by="*[local-name()='lin_id']/text()"> 
    <Results> 
     <xsl:element name="LIN_ID"><xsl:value-of select="*[local-name()='lin_id']"/></xsl:element> 
     <xsl:element name="Count"><xsl:value-of select="sum(current-group()/*[local-name()='qty'])"/></xsl:element> 
    </Results> 
</xsl:for-each-group> 

Voici le fichier XML source:

<Equipment> 
    <lin_id>C18312</lin_id> 
    <qty>5</qty> 
    </Equipment> 
    <Equipment> 
    <lin_id>C18345</lin_id> 
    <qty>22</qty> 
    </Equipment> 
    <Equipment> 
    <lin_id>C18378</lin_id> 
    <qty>43</qty> 
    </Equipment> 
    <Equipment> 
    <lin_id>C18378</lin_id> 
    <qty>208</qty> 
    </Equipment> 

Et voici ce que la sortie est actuellement:

<Results> 
     <LIN_ID>C18312</LIN_Name> 
     <Count>5</Count> 
    </Results> 
    <Results> 
     <LIN_ID>C18345</LIN_Name> 
     <Count>22</Count> 
    </Results> 
     <Results> 
     <LIN_ID>C18378</LIN_Name> 
     <Count>43</Count> 
    </Results> 

Vous peut voir qu'il fait le regroupement, mais pour LIN_ID C18378, il devrait être la somme des deux entrées et la sortie d'un compte de 251 mais au lieu de cela, il affiche simplement l'une des valeurs.

Répondre

1

Tout d'abord - qu'est-ce que <xsl:for-each-group select="//node()" > est supposé faire? Essayez:

<xsl:for-each-group select="//Equipment" group-by="lin_id"> 
    <Results> 
    <LIN_ID> 
     <xsl:value-of select="current-grouping-key()"/> 
    </LIN_ID> 
    <Count> 
     <xsl:value-of select="sum(current-group()/qty)"/> 
    </Count> 
    </Results> 
</xsl:for-each-group> 

Si toute cette affaire *[local-name()='…'] est à cause de namespaces, je vous suggère de faire vos déclarations d'espace de noms droit. Parce que c'est inutile et limite horrible. ;-)

Aussi: Il n'est pas nécessaire d'écrire <xsl:element name="LIN_ID">, vous pouvez simplement écrire <LIN_ID> directement, comme indiqué ci-dessus.

Pour le débogage, vous pouvez faire:

<Count qty_nodes="{count(current-group()/qty)}"> 
    <xsl:value-of select="sum(current-group()/qty)"/> 
</Count> 

pour voir combien de nœuds current-group()/qty retours.

+0

Je suppose que // node() get est le nœud actuel? Je n'ai aucune idée. J'ai hérité de ce fichier xslt et j'apprends juste pour ne pas être offensé par l'horrible déclaration de Bordeline. Je devrais aggree et certains des autres fichiers xslt ont un mélange de déclarations d'espaces de noms et je ne sais quoi d'autre. Ce que tu m'as donné a bien marché. Merci! – John81

+0

Non, // node() sélectionne * chaque noeud * dans le document entier. *Tout*. Vous devriez lire sur XPath. ;-) En outre, le "borderline horrible" a aussi smiley. Si ma réponse a fonctionné, vous pouvez la marquer comme acceptée. Tomalak

+0

Gotcha. Je voudrais marquer comme une réponse, mais j'ai besoin d'une réputation de 15 et seulement 10. Je reviendrai et le faire quand j'ai quelques points de plus. – John81

1

Cette transformation:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" 
> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:template match="/*"> 
     <top> 
      <xsl:for-each-group select="Equipment/lin_id" group-by="."> 
      <Results> 
       <LIN_ID> 
       <xsl:sequence select="current-grouping-key()"/> 
       </LIN_ID> 
       <Count> 
       <xsl:sequence select="sum(current-group()/../qty/xs:integer(.))"/> 
       </Count> 
      </Results> 
      </xsl:for-each-group> 
     </top> 
    </xsl:template> 
</xsl:stylesheet> 

lorsqu'elle est appliquée contre l'entrée fourni (corrigé pour être un fichier XML wellformed):

<t> 
    <Equipment> 
     <lin_id>C18312</lin_id> 
     <qty>5</qty> 
    </Equipment> 
    <Equipment> 
     <lin_id>C18345</lin_id> 
     <qty>22</qty> 
    </Equipment> 
    <Equipment> 
     <lin_id>C18378</lin_id> 
     <qty>43</qty> 
    </Equipment> 
    <Equipment> 
     <lin_id>C18378</lin_id> 
     <qty>208</qty> 
    </Equipment> 
</t> 

produit le résultat recherché:

<top> 
    <Results> 
     <LIN_ID>C18312</LIN_ID> 
     <Count>5</Count> 
    </Results> 
    <Results> 
     <LIN_ID>C18345</LIN_ID> 
     <Count>22</Count> 
    </Results> 
    <Results> 
     <LIN_ID>C18378</LIN_ID> 
     <Count>251</Count> 
    </Results> 
</top> 
+0

Pourquoi '' au lieu de ''? – Tomalak

+0

C'est une bonne habitude dans XSLT 2.0 de toujours utiliser et d'utiliser seulement pour produire un nœud de texte. Ils ne sont équivalents que lorsque nous sommes sûrs que la valeur sera dans la sortie finale. Même alors, si la valeur n'est pas la sortie * complete *, il vaut mieux utiliser .Si nous utilisons , le noeud de texte créé devra être fusionné avec d'autres noeuds de texte pour produire la sortie finale. En bref: Toujours utiliser . J'utilise dans certains cas particuliers: lorsque je produis plusieurs valeurs et que je veux utiliser l'attribut @separator. –