2009-09-30 9 views
1

Je veux trier les nœuds en fonction des attributs. Dites qu'il y a trois attributs A, B et C dans l'élément E1. Je sais qu'un sous-groupe de nœuds a la même valeur d'attribut A et B. Comment puis-je obtenir ce sous-groupe récupérer le nœud qui a la valeur maximale de C? La partie délicate ici est que je ne sais pas quelle est la valeur de A. Je sais juste que ce sous-groupe partage la même valeur de A. Tout comme un index à deux clés.Trier les nœuds en fonction de plusieurs attributs?

Je pense utiliser pour chaque sous-groupe pour chaque groupe.

exemple

<masterNodes> 
    <Node> 
     <Element1 A="123" B="LEFT" C="1"> 
     <Element2>...</Element2> 
    </Node> 
    <Node> 
     <Element1 A="123" B="DOWN" C="5"> 
     <Element2>...</Element2> 
    </Node> 
    <Node> 
     <Element1 A="abc" B="RIGHT" C="2"> 
     <Element2>...</Element2> 
    </Node> 
    <Node> 
     <Element1 A="123" B="LEFT" C="3"> 
     <Element2>...</Element2> 
    </Node> 
    <Node> 
     <Element1 A="4XX" B="LEFT" C="4"> 
     <Element2>...</Element2> 
    </Node> 
    <Node> 
     <Element1 A="abc" B="RIGHT" C="1"> 
     <Element2>...</Element2> 
    </Node> 
    <Node> 
     <Element1 A="4XX" B="LEFT" C="5"> 
     <Element2>...</Element2> 
    </Node> 
    <Node> 
     <Element1 A="4XX" B="UP" C="0"> 
     <Element2>...</Element2> 
    </Node> 
</masterNodes> 

Comment puis-je n'écrire la valeur maximale de C pour le noeud avec la même valeur de A et B?

Voici comment je structure mon code. Mais je ne le fais jamais fonctionner.

<xsl:for-each-group select="/Node/Element1" group-by="@A"> 
    <xsl:for-each select=".[@B='LEFT']"> 
     <xsl:sort select="@C" data-type="number" order="descending"/> 
     <xsl:if test="position()=1"><xsl:value-of select="@C"/></xsl:if> 
    </xsl:for-each><xsl:text>&#xD;</xsl:text> 
    <xsl:for-each select=".[@B='RIGHT']"> 
     <xsl:sort select="@C" data-type="number" order="descending"/> 
     <xsl:if test="position()=1"><xsl:value-of select="@C"/></xsl:if> 
    </xsl:for-each><xsl:text>&#xD;</xsl:text> 
    <same for other direction> 
</xsl:for-each-group> 

Quelque chose ne va pas?

Répondre

0

Je pense que cela pourrait être réalisé par 'groupement muenchian' qui utilise l'élément xsl: key pour regrouper les nœuds.

Tout d'abord, définir une clé d'éléments ELEMENT1 en utilisant A et B attribue

<xsl:key name="Elements" match="Element1" use="concat(@A,@B)"/> 

Ensuite, vous devrez boucle throught les combinaisons uniques de A et B à l'aide de cette

clé
<xsl:for-each select="//Element1[generate-id(.) = generate-id(key(&apos;Elements&apos;, concat(@A,@B))[1])]"> 

Au sein cette boucle, vous bouclez encore, mais seulement sur les éléments avec les clés correspondantes, cette fois dans l'ordre de l'attribut C

<xsl:for-each select="key('Elements', concat(@A,@B))"> 
    <xsl:sort select="@C" order="descending"/> 

Comme vous ne voulez que le premier élément, qui a

<xsl:if test="position() = 1"> 

Mettre ce tout à fait donne

<xsl:key name="Elements" match="Element1" use="concat(@A,@B)"/> 

<xsl:template match="/"> 
    <xsl:for-each select="//Element1[generate-id(.) = generate-id(key('Elements', concat(@A,@B))[1])]"> 
     <xsl:sort select="@C" order="descending"/> 
     <xsl:for-each select="key('Elements', concat(@A,@B))"> 
      <xsl:sort select="@C" order="descending"/> 
      <xsl:if test="position() = 1"> 
      (<xsl:value-of select="@A"/>,<xsl:value-of select="@B"/>,<xsl:value-of select="@C"/>) 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:for-each> 
</xsl:template> 
1

la plus haute valeur de l'attribut C, alors vous tester la position() Si je comprends spec correctement, l'élément de contexte à l'intérieur de chaque groupe est défini sur le premier élément de ce groupe. Pour trier le groupe, vous devez utiliser la fonction current-group(). Le modèle suivant semble fonctionner:

<xsl:template match="/masterNodes"> 
    <xsl:for-each-group select="Node/Element1" group-by="@A"> 
     <xsl:for-each select="current-group()[@B='LEFT']"> 
      <xsl:sort select="@C" data-type="number" order="descending"/> 
      <xsl:if test="position()=1"><xsl:value-of select="concat(@A, ' ', @B, ' ', @C)"/></xsl:if> 
     </xsl:for-each> 
     <xsl:text>&#xD;</xsl:text> 
     <xsl:for-each select="current-group()[@B='RIGHT']"> 
      <xsl:sort select="@C" data-type="number" order="descending"/> 
      <xsl:if test="position()=1"><xsl:value-of select="concat(@A, ' ', @B, ' ', @C)"/></xsl:if> 
     </xsl:for-each> 
     <xsl:text>&#xD;</xsl:text> 
    </xsl:for-each-group> 

</xsl:template> 
+0

+1, mais je pense que l'OP veut 'concat de groupe = (@A, @B)" ' – Tomalak

Questions connexes