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 :

Défi Septembre 2004


Sujet :

XSL/XSLT/XPATH XML

  1. #21
    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 : 48
    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
    allez on n'a le droit au following-sibling ca fera plaisir au vieux
      0  0

  2. #22
    Membre confirmé
    Avatar de grishka
    Inscrit en
    Janvier 2003
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Janvier 2003
    Messages : 285
    Points : 499
    Points
    499
    Par défaut
    bon voici une solution qui a l'air de fonctionner :

    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
    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     
       <xsl:output method="text"/>
     
       <xsl:template match="racine">
          <xsl:call-template name="sommeniveau">
             <xsl:with-param name="resultat" select="0"/>
             <xsl:with-param name="noeud" select="n[position()=1]"/>
          </xsl:call-template>
       </xsl:template>
     
       <xsl:template name="sommeniveau">
          <xsl:param name="resultat"/>
          <xsl:param name="noeud"/>
     
         <xsl:choose>
            <xsl:when test="$noeud">
             <xsl:variable name="ssres">
                <xsl:if test="$noeud/n">
                   <xsl:call-template name="sommeniveau">
                      <xsl:with-param name="resultat" select="0"/>
                      <xsl:with-param name="noeud" select="$noeud/n[position()=1]"/>
                   </xsl:call-template>
                </xsl:if>
                <xsl:if test="not($noeud/n)">0</xsl:if>
             </xsl:variable>
             <xsl:variable name="somme">
               <xsl:choose>
                <xsl:when test="$noeud/@valeur &gt; number($ssres)">
                  <xsl:value-of select="$resultat+number($ssres)+$noeud/@valeur"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="$resultat+number($ssres)"/>
                </xsl:otherwise>
               </xsl:choose>
             </xsl:variable>
             <xsl:call-template name="sommeniveau">
               <xsl:with-param name="resultat" select="number($somme)"/>
               <xsl:with-param name="noeud" select="$noeud/following-sibling::*"/>
             </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$resultat"/>
            </xsl:otherwise>
         </xsl:choose>
     
       </xsl:template>
     
    </xsl:stylesheet>
      0  0

  3. #23
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Bravo grégory !
    Maintenant, à moi de poser un défi : transformer une structure linéaire en structure arborescente
    Soit le document XML suivant :
    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
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <document>
      <section niveau="1" titre="1"/>
      <texte>aaaa</texte>
      <section niveau="2" titre="1.1"/>
      <texte>bbbb</texte>
      <section niveau="3" titre="1.1.1"/>
      <texte>cccc</texte>
      <section niveau="3" titre="1.1.2"/>
      <texte>dddd</texte>
      <section niveau="2" titre="1.2"/>
      <texte>eeee</texte>
      <section niveau="3" titre="1.2.1"/>
      <texte>ffff</texte>
      <section niveau="2" titre="1.3"/>
      <texte>gggg</texte>
      <texte>hhhh</texte>
      <section niveau="3" titre="1.3.1"/>
      <section niveau="4" titre="1.3.1.1"/>
      <texte>iiii</texte>
      <section niveau="4" titre="1.3.1.2"/>
      <texte>jjjj</texte>
      <section niveau="1" titre="2"/>
      <texte>kkkk</texte>
      <section niveau="2" titre="2.1"/>
      <texte>llll</texte>
      <section niveau="2" titre="2.2"/>
      <texte>mmmm</texte>
    </document>
    A chaque section est attribué un niveau qui indique sa position dans le plan du document. Ainsi, les sections de niveau 1 sont les chapitres principaux du document, les sections de niveau 2 les sous-chapitres de ces chapitres, etc. (les connaisseurs auront reconnu une version (très) simplifiée des documents Writer de OpenOffice )
    Ecrire la feuille de style XSL qui transformera ce document en une arborescence :
    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
    <?xml version="1.0" encoding="UTF-8"?>
    <document>
      <section titre="1">
        <texte>aaaa</texte>
        <section titre="1.1">
          <texte>bbbb</texte>
          <section titre="1.1.1">
            <texte>cccc</texte>
          </section>
          <section titre="1.1.2">
            <texte>dddd</texte>
          </section>
        </section>
        <section titre="1.2">
          <texte>eeee</texte>
          <section titre="1.2.1">
            <texte>ffff</texte>
          </section>
        </section>
        <section titre="1.3">
          <texte>gggg</texte>
          <texte>hhhh</texte>
          <section titre="1.3.1">
            <section titre="1.3.1.1">
              <texte>iiii</texte>
            </section>
            <section titre="1.3.1.2">
              <texte>jjjj</texte>
            </section>
          </section>
        </section>
      </section>
      <section titre="2">
        <texte>kkkk</texte>
          <section titre="2.1">
            <texte>llll</texte>
          </section>
          <section titre="2.2">
            <texte>mmmm</texte>
          </section>
      </section>
    </document>
    Les règles de transformation sont les suivantes :
    - Chaque section devient un enfant de la section de niveau inférieur qui la précède immédiatement
    - Chaque noeud texte devient enfant de la section qui le précède immédiatement
    - Les attributs titre sont recopiés tels quels (ils ne sont là que pour faciliter la compréhension ; leur contenu étant arbitraire, il est interdit de se baser dessus pour résoudre le problème !)
      0  0

  4. #24
    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 : 48
    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
    Ben il est ou le defi :
    Bon allez j'exagere, ca m'a quand meme prix 45mn pour le trouver et 10 pour l'optimiser.Sympa,un peu facile mais sympa 8)
    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
     
    <?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:template match="/">
    		<xsl:element name="document">
    			<xsl:apply-templates select="document/section[1]"/>
    		</xsl:element>
    	</xsl:template>
    	<xsl:template match="section">
    		<xsl:variable name="pos" select="@niveau"/>
    		<xsl:copy>
    			<xsl:attribute name="titre"><xsl:value-of select="@titre"/></xsl:attribute>
    			<xsl:apply-templates select="following-sibling::*[1][name()='texte']"/>
    			<xsl:apply-templates select="following-sibling::section[1][@niveau &gt; $pos]"/>
    		</xsl:copy>
    		<xsl:apply-templates select="following-sibling::section[@niveau &lt;= $pos][1][@niveau=$pos]"/>
    	</xsl:template>
    	<xsl:template match="texte">
    		<xsl:copy-of select="."/>
    		<xsl:apply-templates select="following-sibling::*[1][name()='texte']"/>
    	</xsl:template>
    </xsl:stylesheet>
      0  0

  5. #25
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Pas mal, y'a de l'idée. Mais il y aussi beaucoup plus simple. Tu peux notamment faire l'économie de ta variable $pos et de deux apply-templates.

    Trop de récursivité, mon petit, trop de récursivité...
      0  0

  6. #26
    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 : 48
    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
    Citation Envoyé par GrandFather
    Trop de récursivité, mon petit, trop de récursivité...
    Ok colonel, vous n'êtes pas enccore si rouillé que ça
    Cela vous siet-il plus?
    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
     
    <?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:template match="/">
       <xsl:element name="document">
          <xsl:apply-templates select="document/section[@niveau=1]"/>
       </xsl:element>
    </xsl:template>
     
    <xsl:template match="section">
       <xsl:copy>
          <xsl:attribute name="titre">
             <xsl:value-of select="@titre"/>
          </xsl:attribute>
     
    <xsl:apply-templates select="following-sibling::texte[(generate-id(./following-sibling::section[1])=generate-id(current()/following-sibling::section[1]))]"/>
     
    <xsl:apply-templates select="following-sibling::section[@niveau =current()/@niveau+1 and (generate-id(./preceding-sibling::section[@niveau=current()/@niveau][1])=generate-id(current()))]"/>
     
       </xsl:copy>
    </xsl:template>
    <xsl:template match="texte">
       <xsl:copy-of select="."/>
    </xsl:template>
    </xsl:stylesheet>
      0  0

  7. #27
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Bravo erwy ! Chapeau !
    Je me permets de poster mon corrigé uniquement parce que tu t'es un peu compliqué la vie pour les noeuds texte et qu'il est un peu plus optimisé (l'id du noeud courant n'est calculé qu'une seule fois, plutôt qu'à chaque évaluation de prédicat)
    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
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
     
      <xsl:output method="xml" indent="yes"/>
     
      <xsl:template match="/document">
        <xsl:copy>
          <xsl:apply-templates select="section[@niveau = 1]"/>
        </xsl:copy>
      </xsl:template>
     
      <xsl:template match="section">
        <xsl:variable name="id_noeud" select="generate-id(.)"/>
        <xsl:copy>
          <xsl:copy-of select="@titre"/>
          <xsl:apply-templates select="following-sibling::texte[generate-id(preceding-sibling::section[1]) = $id_noeud]"/>
          <xsl:apply-templates select="following-sibling::section[(@niveau = current()/@niveau + 1) and (generate-id(preceding-sibling::section[@niveau = current()/@niveau][1]) = $id_noeud)]"/>
        </xsl:copy>
      </xsl:template>
     
      <xsl:template match="texte">
        <xsl:copy-of select="."/>
      </xsl:template>
     
    </xsl:stylesheet>
      0  0

  8. #28
    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 : 48
    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
    Citation Envoyé par GrandFather
    Bravo erwy ! Chapeau !
    Je me permets de poster mon corrigé uniquement parce que tu t'es un peu compliqué la vie pour les noeuds texte et qu'il est un peu plus optimisé (l'id du noeud courant n'est calculé qu'une seule fois, plutôt qu'à chaque évaluation de prédicat)
    En effet, mais c'est tjrs le pb quand tu viens de taper un xpath de trois lignes quand tu en ecris un 1,5 ligne derriere tu as l'impression de l'avoir optimise
    Par contre pour la variable je suis vexé ta precedente reflexion m'avait fait penser que tu n'en utilisais pas
      0  0

  9. #29
    Membre confirmé
    Avatar de grishka
    Inscrit en
    Janvier 2003
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Janvier 2003
    Messages : 285
    Points : 499
    Points
    499
    Par défaut
    j'ai l'impression que les défis ne résistent pas bien longtemps ici
    par contre erwy et grandfather, pourriez vous expliquer un peu les points qui peuvent paraitre difficiles dans vos solutions?
      0  0

  10. #30
    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 : 48
    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
    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
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
     
      <xsl:output method="xml" indent="yes"/>
     
      <xsl:template match="/document">
        <xsl:copy>
          <xsl:apply-templates select="section[@niveau = 1]"/>
        </xsl:copy>
      </xsl:template>
     
      <xsl:template match="section">
        <xsl:variable name="id_noeud" select="generate-id(.)"/>
        <xsl:copy>
          <xsl:copy-of select="@titre"/>
          <xsl:apply-templates select="following-sibling::texte[generate-id(preceding-sibling::section[1]) = $id_noeud]"/>
          <xsl:apply-templates select="following-sibling::section[(@niveau = current()/@niveau + 1) and (generate-id(preceding-sibling::section[@niveau = current()/@niveau][1]) = $id_noeud)]"/>
        </xsl:copy>
      </xsl:template>
     
      <xsl:template match="texte">
        <xsl:copy-of select="."/>
      </xsl:template>
     
    </xsl:stylesheet>
    Je vais surtout detaille les <section> ,le traitement des <texte> en decoule en plus simple.
    L'algo en lui meme est asez simple,le point complique est le xpath utilise pour selectionner tous les "enfants" du noeud que l'on est en train de recopier.
    Un premier point le generate-id(nodeset),attribut un identifiant unique a chaque noeud de l'arbre, pour verifier que deux xpath pointe sur le meme noeud il suffit donc de comparer generate-id(xpath1)=generate-id(xpath2)
    quels sont les propriétes d'un "enfant"
    -Il suit le noeud pere et est une section >>following-sibling::section
    -son niveau est incrementé de 1 par rapport au pere>> niveau = current()/@niveau + 1
    -Son pere est le premier element de niveau inferieur(c'est l'element courant) qui est au dessus de lui

    pere=current()
    premier element...= preceding-sibling::section[@niveau = current()/@niveau][1]
    il ne reste plus qu' a comparer leur id
    (generate-id(preceding-sibling::section[@niveau = current()/@niveau][1]) = $id_noeud)
    et a additioner tous ces element avec un et pour produire le bon xpath
    following-sibling::section[(@niveau = current()/@niveau + 1) and (generate-id(preceding-sibling::section[@niveau = current()/@niveau][1]) = $id_noeud)]
      0  0

  11. #31
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 43
    Points : 35
    Points
    35
    Par défaut
    Vous en avez pas d'autre, car j'adore cette idée de défie, je suis débutant dans le xsl mais je vais essayer de faire les premiers qui ont été posté.
      0  0

Discussions similaires

  1. Votre EDI préferé pour Java (2003-2004) ?
    Par christopheJ dans le forum EDI et Outils pour Java
    Réponses: 73
    Dernier message: 17/10/2005, 17h05
  2. [MX 2004] Flash du dessin
    Par Admin dans le forum Flash
    Réponses: 9
    Dernier message: 23/11/2003, 18h40
  3. [MX 2004] Timer
    Par Admin dans le forum Flash
    Réponses: 5
    Dernier message: 23/11/2003, 00h16
  4. [mx 2004 ] Xml
    Par bolo dans le forum Flash
    Réponses: 10
    Dernier message: 22/11/2003, 23h26

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