2009-12-18 5 views
5

XSL Vu le code XML suivant:Exécution d'un « groupe par » requête dans XPath

<results name="queryResults"> 
    <int name="intfield1:[* TO 10]">11</int> 
    <int name="intfield2:[10 TO 20]">9</int> 
    <int name="intfield1:[10 TO 20]">12</int> 
</results> 

je voudrais produire ce XML:

<results> 
    <field name="numberfield1"> 
     <value name="[* TO 10]">11</value> 
     <value name="[10 TO 10]">12</value> 
    </field> 
    <field name="numberfield2"> 
     <value name="[10 TO 20]">9</value> 
    </field> 
</results> 

Je ne peux pas penser comment faire en principalement parce que je XSL suis vouloir groupe par le numbericfield .. Tout ce que je peux trouver est la suivante:

<xsl:if test="count(results/int) &gt; 0"> 
    <results> 
    <xsl:for-each select="results/int"> 
     <field> 
      <xsl:attribute name="name"> 
       <xsl:value-of select="substring-before(@name, ':')"/></xsl:attribute> 
      <value> 
       <xsl:attribute name="name"> 
        <xsl:value-of select="substring-after(@name, ':') "/> 
       </xsl:attribute> 
       <xsl:value-of select="."/> 
      </value> 
     </field> 
    </xsl:for-each> 
    </results> 
</xsl:if> 

Toutefois, cela ne produit pas le beau groupe liste ed place i obtenir ceci:

<results> 
    <field name="numberfield1"> 
     <value name="[* TO 10]">11</value> 
    </field> 
    <field name="numberfield2"> 
     <value name="[10 TO 20]">9</value> 
    </field> 
    <field name="numberfield1"> 
     <value name="[10 TO 10]">12</value> 
    </field> 
</results> 

Si quelqu'un peut me TSAR dans la bonne direction .. Ce serait génial?

Merci

Répondre

11

Pour ce faire, dans XSLT 1.0, vous devrez utiliser une technique appelée "muenchian grouping". Tout d'abord créer une clé des nœuds sur lesquels vous souhaitez groupe

<xsl:key name="intfield" match="int" use="substring-before(@name, ':')" /> 

Ensuite, vous itérer à travers tous les nœuds, mais seulement sélectionner ceux qui se trouvent d'abord dans le groupe concerné

<xsl:for-each select="int[generate-id() = generate-id(key('intfield', substring-before(@name, ':'))[1])]"> 

Ensuite, vous pouvez itérer utiliser la clé pour itérer sur tous les nœuds du groupe

<xsl:variable name="intfieldname" select="substring-before(@name, ':')"/> 
<xsl:for-each select="key('intfield', $intfieldname)"> 

Mettre cela donne tous ensemble

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml"/> 
    <xsl:key name="intfield" match="int" use="substring-before(@name, ':')"/> 
    <xsl:template match="/results"> 
     <results> 
     <xsl:for-each select="int[generate-id() = generate-id(key('intfield', substring-before(@name, ':'))[1])]"> 
      <xsl:variable name="intfieldname" select="substring-before(@name, ':')"/> 
      <field> 
       <xsl:attribute name="name"> 
        <xsl:value-of select="$intfieldname"/> 
       </xsl:attribute> 
       <xsl:for-each select="key('intfield', $intfieldname)"> 
        <value> 
        <xsl:attribute name="name"> 
         <xsl:value-of select="substring-after(@name, ':')"/> 
        </xsl:attribute> 
        <xsl:value-of select="."/> 
        </value> 
       </xsl:for-each> 
      </field> 
     </xsl:for-each> 
     </results> 
    </xsl:template> 
</xsl:stylesheet> 

Dans votre exemple, 'intfield' devient 'numberfield'. J'ai gardé le nom "intfield" dans l'exemple ci-dessus.

  • typo fixe.
+0

Vous l'homme .. .. hourras juste essayé et il fonctionne un régal. Je vais devoir chercher ce truc de "meunchian grouping" comme pour le moment tout cela ressemble à du vaudou – CraftyFella

+0

Une question ... Y at-il un moyen de limiter les champs int qu'il crée ... comme il y a une autre liste d'int's else où et ça amène ceux-ci dans la clé intfield? Espérons que cela a du sens – CraftyFella

+1

Oui, dans l'attribut 'match' de la clé xsl: vous pouvez entrer une expression Xpath complète pour être plus précis sur les nœuds dont vous avez besoin. Par exemple

3

Le groupement Muenchian est un travail de génie. Ce n'est pas facile à comprendre, mais voyez: http://www.jenitennison.com/xslt/grouping/muenchian.html

Pour simplifier le processus, le W3C a spécifiquement pris en charge le regroupement dans XSLT2.0. Voir, par exemple: http://www.xml.com/pub/a/2003/11/05/tr.html

Cependant, tous les environnements supportent XSLT2.0

+0

En utilisant MS .NET si seulement XSL 1.0 pour moi .. vous avez raison .. il est un travail de génie .. Je vais lire ce lien. Merci – CraftyFella