IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

XSL/XSLT/XPATH XML Discussion :

[XSLT] Regroupement et cie.


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Membre expérimenté
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    1 466
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 466
    Points : 1 610
    Points
    1 610
    Par défaut [XSLT] Regroupement et cie.
    Hello,
    J'aimerais faire un regroupement assez complexe, donc avis au pro de la méthode de muench ( http://www.jenitennison.com/xslt/gro...muenchian.html )!
    Le plus parlant étant un exemple, en voici un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <?xml version="1.0" encoding="UTF-8"?>
    <list>
    	<a seq="1">
    		<b />
    	</a>
    	<a seq="2" keep="true">
    		<b />
    	</a>
    	<a seq="3" keep="true">
    		<b />
    	</a>
    	<a seq="4">
    		<b />
    	</a>
    	<a seq="5">
    		<b />
    	</a>
    	<a seq="6" keep="true">
    		<b />
    	</a>
    	<a seq="7">
    		<b />
    	</a>
     
    	<a seq="8" keep="true">
    		<b />
    	</a>
    </list>
    J'ai ajouté l'attribut "seq" par soucis de lisibilité mais il n'est pas présent dans mon cas.

    En gros, je veux grouper sous un même groupe les noeuds consécutifs qui ont l'attribut keep='true' ainsi qu'éventuellement, le premier qui les suit qui n'a pas l'attribut "keep".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <?xml version="1.0" encoding="UTF-8"?>
    <list>
    	<a seq="1">
    		<b />
    	</a>
    	<group>
    		<a debug="1" seq="2" keep="true">
    			<b />
    		</a>
    		<a seq="3" keep="true">
    			<b />
    		</a>
    		<a seq="4">
    			<b />
    		</a>
    	</group>
    	<a seq="5">
    		<b />
    	</a>
    	<group>
    		<a debug="1" seq="6" keep="true">
    			<b />
    		</a>
    		<a seq="7">
    			<b />
    		</a>
    	</group>
     
    	<group>
    		<a debug="1" seq="8" keep="true">
    			<b />
    		</a>
    	</group>
    </list>
    Pour le moment j'ai fait que ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     
    <xsl:key 
    use="generate-id(preceding-sibling::*[@keep='true' and preceding-sibling::*[1][not(@keep)]][1])"
     name="next" 
     match="a[@keep='true' and preceding-sibling::*[1][@keep='always']]"/>
     
    <xsl:template match="a[@keep='true' and preceding-sibling::*[1][not(@keep)]]">
      <group>
      <xsl:copy>
    	<xsl:attribute name="debug">1</xsl:attribute>
    	<xsl:apply-templates select="@*" />
    	<xsl:apply-templates select="*" />
      </xsl:copy>
      <xsl:for-each select="key('next',generate-id(node()))">
    	  <xsl:copy>
    		<xsl:attribute name="debug">1</xsl:attribute>
    		<xsl:apply-templates select="@*" />
    		<xsl:apply-templates select="*" />
    	  </xsl:copy>
      </xsl:for-each>
      </group>
    </xsl:template>
     
     <xsl:template match="@*|node()">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>
    Des idées?

  2. #2
    Membre expérimenté
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    1 466
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 466
    Points : 1 610
    Points
    1 610
    Par défaut
    J'ai résolu mon pb en passant par la récursion plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    	<xsl:template match="/">
    		<xsl:copy>
    			<xsl:apply-templates select="*"/>
    		</xsl:copy>
    	</xsl:template>
     
    	<xsl:template match="*[@keep='true' and preceding-sibling::*[1][not(@keep='true')]]">
    		<xsl:variable name="position" select="count(preceding-sibling::*)"/>
    		<group pos="{$position}">
     
    			<xsl:call-template name="copyFollowingKeep">
    				<xsl:with-param name="position" select="$position+1"/>
    				<xsl:with-param name="parent" select="parent::node()"/>
    			</xsl:call-template>
    		</group>
    	</xsl:template>
     
    	<xsl:template match="*" mode="cell">
    		<cell>
    			<xsl:copy>
    				<xsl:apply-templates select="@*"/>
    				<xsl:apply-templates select="*"/>
    			</xsl:copy>
    		</cell>
    	</xsl:template>
     
    	<xsl:template name="copyFollowingKeep">
    		<xsl:param name="parent"/>
    		<xsl:param name="position"/>
     
    		<xsl:apply-templates select="$parent/*[$position]" mode="cell"/>
     
    		<xsl:if test="$parent/*[$position]/@keep='true'">
    			<xsl:call-template name="copyFollowingKeep">
    				<xsl:with-param name="position" select="$position+1"/>
    				<xsl:with-param name="parent" select="parent::node()"/>
    			</xsl:call-template>
    		</xsl:if>
    	</xsl:template>
     
    	<xsl:template match="*[preceding-sibling::*[1][@keep='true']]">
    	</xsl:template>
     
    	<xsl:template match="@*|node()">
    		<xsl:copy>
    			<xsl:apply-templates select="@*|node()"/>
    		</xsl:copy>
    	</xsl:template>
     
    </xsl:stylesheet>
    Edit : petite correction du calcul de la position

  3. #3
    Rédacteur

    Avatar de Erwy
    Homme Profil pro
    Développeur Web
    Inscrit en
    Novembre 2003
    Messages
    4 967
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 967
    Points : 10 927
    Points
    10 927
    Par défaut
    comme je suis un tantinet pris actuellement ma particpation est fluctuante, dommage car c'est tout à fait le type de problème rigolo qui m'amuse.
    Si une autre solution t'intéresse voici la mienne qui me semble correspondre à ce qui est demandé

    1) deux groupes :
    - ceux qui ne sont pas precede d'un élément avec l'attribut keep=true
    - les autres

    les éléments du deuxième sont indexé avec l'id du précedent

    2)deux parcours
    le premier parcours sequentielle sur le premier groupe
    si pas attribut copie
    si attribut cree le groupe et commence deuxième parcours

    3) deuxième parcours : grace au premier parcours on a le premier élément hors on connait son fils grace au groupe et on continue ainsi...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    	<xsl:key name="pasprecede" match="a[not((preceding-sibling::a[1])[@keep='true'])]" use="generate-id()"/>
    	<xsl:key name="precede" match="a[(preceding-sibling::a[1])[@keep='true']]" use="generate-id(preceding-sibling::a[1])"/>
    	<xsl:template match="/">
    		<list>
    			<xsl:apply-templates select="*/*[key('pasprecede',generate-id())]" mode="premier"/>
    		</list>
    	</xsl:template>
    	<xsl:template match="a[not(@keep='true')]" mode="premier">
    		<xsl:copy-of select="."/>
    	</xsl:template>
    	<xsl:template match="a[@keep='true']" mode="premier">
    		<group>
    			<xsl:copy-of select="."/>
    			<xsl:apply-templates select="key('precede',generate-id())" mode="suivant"/>
    		</group>
    	</xsl:template>
    	<xsl:template match="a" mode="suivant">
    		<xsl:copy-of select="."/>
    		<xsl:apply-templates select="key('precede',generate-id())" mode="suivant"/>
    	</xsl:template>
    </xsl:stylesheet>
    PS: on notera qu'on peut simplier le code, la première clé n'est par exemple pas indispensable, je l'ai surtout laissé pour garder l'esprit de l'algo

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XSLT]Regroupement par attribut.
    Par zserdtfg dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 08/12/2006, 11h35
  2. [XSLT] regrouper des noeuds identiques
    Par DelphLaga dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 14/11/2006, 17h07
  3. [XSLT] Regrouper les noeuds qui se ressemblent
    Par yos dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 19/10/2006, 16h51
  4. [XSLT] Regroupement ds XML
    Par Virginie dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 19/10/2006, 12h35
  5. [XSLT] Regroupement en utilsant xsl:key
    Par AVRAVR dans le forum XSL/XSLT/XPATH
    Réponses: 5
    Dernier message: 28/07/2006, 10h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo