2010-06-05 11 views
1

Je souhaite trier un fichier XML de forme libre à l'aide de plusieurs attributs (d'abord par T, puis par L). Le XML est un peu complexe et il est structuré comme indiqué ci-dessous:Tri du fichier XML via plusieurs attributs

<?xml version="1.0" encoding="utf-8"?> 
<wb xmlns:cf="http://www.macromedia.com/2004/cfform" xmlns:a="urn:dummy"> 
    <a:form name="chart"> 
    <a:fieldset FIELD="a" FIELDNAME="FieldSet1"> 
     <a:select1 FIELDNUMBER="01" L="1" T="2" /> 
     <a:input FIELDNUMBER="02" INDEX="4" L="200" T="1" /> 
    </a:fieldset> 
    <a:fieldset FIELD="b" FIELDNAME="FieldSet1"> 
     <a:select1 FIELDNUMBER="03" T="3" L="1" /> 
     <a:input FIELDNUMBER="04" INDEX="7" T="4" L="200" /> 
     <a:fieldset FIELD="c" FIELDNAME="FieldSet1"> 
     <a:input FIELDNUMBER="05" T="10" INDEX="6" L="400" /> 
     <a:input FIELDNUMBER="06" T="8" INDEX="8" L="200" /> 
     </a:fieldset> 
    </a:fieldset> 
    <a:input FIELDNUMBER="08" INDEX="3" L="3" T="5" /> 
    <a:input FIELDNUMBER="09" INDEX="2" L="2" T="5" /> 
    </a:form> 
</wb> 

PS:

  1. L'élément racine est wb, ce qui est toujours suivie d'une: forme
  2. Le L et T sont toujours trouvés dans les éléments qui ont une étiquette dans l'espace de noms a, la seule exception étant un: fieldset qui n'a pas L et T
  3. a: fieldset peut avoir plusieurs enfants de l'espace de noms a dont un autre a: fieldset
  4. Lors du tri des enfants qui sont dans un fieldset, ceux-ci doivent rester attachés à leur parent courant.

La sortie résultante doit être le suivant:

<?xml version="1.0" encoding="utf-8"?> 
<wb xmlns:cf="http://www.macromedia.com/2004/cfform" xmlns:a="urn:dummy"> 
    <a:form name="chart"> 
    <a:fieldset FIELD="a" FIELDNAME="FieldSet1"> 
     <a:input FIELDNUMBER="02" INDEX="4" L="200" T="1" /> 
     <a:select1 FIELDNUMBER="01" L="1" T="2" /> 
    </a:fieldset> 
    <a:fieldset FIELD="b" FIELDNAME="FieldSet1"> 
     <a:select1 FIELDNUMBER="03" T="3" L="1" /> 
     <a:input FIELDNUMBER="04" INDEX="7" T="4" L="200" /> 
     <a:fieldset FIELD="c" FIELDNAME="FieldSet1"> 
     <a:input FIELDNUMBER="06" T="8" INDEX="8" L="200" /> 
     <a:input FIELDNUMBER="05" T="10" INDEX="6" L="400" /> 
     </a:fieldset> 
    </a:fieldset> 
    <a:input FIELDNUMBER="09" INDEX="2" L="2" T="5" /> 
    <a:input FIELDNUMBER="08" INDEX="3" L="3" T="5" /> 
    </a:form> 
</wb> 

Pour une meilleure compréhension, on peut supposer que L représente gauche et T désigne Top. Donc, l'idée de ceci est que quand je regarde le XML transformé je peux immédiatement noter quels éléments précèdent quoi.

Que pensez-vous de cela?

+0

Pas clair! Quelle devrait être la sortie résultante pour le document XML fourni? S'il vous plaît, éditez votre question. –

+0

Quelles sont les règles de tri des éléments a: fieldset réels dans le formulaire a: (ou dans d'autres a: fieldsets). Pour la forme a:, les champs apparaissent comme le premier des enfants. Dans le deuxième fieldset enfant, les fieldsets sont les derniers des enfants. –

+0

Tout doit être trié globalement d'abord par T puis par L. Chaque niveau doit être trié indépendamment. Ainsi, a: les éléments de formulaire (enfants de niveau 1 w.r.t a: forme) doivent être triés indépendamment des enfants des autres niveaux (niveau 2 et supérieur). Dans mon exemple, en ignorant les éléments a: fieldset, il n'y a que 2 enfants de niveau 1 (fieldnumber = "09" et fieldnumber = "08"). Ensuite, les éléments de fieldset avec field = "b", qui sont 2 - fieldnumber = "03" et fieldnumber = "04", doivent être triés indépendamment du niveau 1 ou de fieldset avec field = "c". Le même raisonnement suit pour les autres nœuds. – user164701

Répondre

0

essayez ceci: (faire quelques changements si je ne l'ai pas compris vos questions correctement)

<xsl:template match="/wb"> 
    <xsl:copy> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates mode="aaa" select="."/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="*" mode="aaa"> 
    <xsl:if test="child::*[1][not(@T) or not(@L)]"> 
     <xsl:for-each select="child::*[not(@T) or not(@L)]"> 
     <xsl:copy> 
      <xsl:copy-of select="@*"/> 
      <xsl:apply-templates mode="aaa" select="."/> 
     </xsl:copy> 
     </xsl:for-each> 
    </xsl:if> 
    <xsl:variable name="sorted1"> 
     <xsl:for-each select="a:*[@T and @L]"> 
     <xsl:sort select="@T" data-type="number" order="ascending"></xsl:sort> 
     <xsl:copy> 
      <xsl:copy-of select="@*"/> 
     </xsl:copy> 
     </xsl:for-each> 
    </xsl:variable> 
    <xsl:for-each select="msxsl:node-set($sorted1)/*[not(@T=preceding-sibling::*/@T)]"> 
     <xsl:variable name="tval" select="@T"/> 
     <xsl:for-each select="msxsl:node-set($sorted1)/*[@T=$tval]"> 
     <xsl:sort select="@L" data-type="number" order="ascending"></xsl:sort> 
     <xsl:copy> 
      <xsl:copy-of select="@*"/> 
     </xsl:copy> 
     </xsl:for-each> 
    </xsl:for-each> 

    <xsl:if test="not(child::*[1][not(@T) or not(@L)])"> 
     <xsl:for-each select="child::*[not(@T) or not(@L)]"> 
     <xsl:copy> 
      <xsl:copy-of select="@*"/> 
      <xsl:apply-templates mode="aaa" select="."/> 
     </xsl:copy> 
     </xsl:for-each> 
    </xsl:if> 

    </xsl:template>