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]copie partielle avec condition sur les axes


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Rédacteur
    Avatar de MasterOfChakhaL
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2004
    Messages
    2 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 147
    Points : 3 264
    Points
    3 264
    Par défaut [XSLT]copie partielle avec condition sur les axes
    Bonjour,

    Je tente de simplifier un fichier xml via une feuille xsl de la manière suivante:

    En connaissant un noeud de mon arborescence, j'aimerai obtenir une nouvelle arborescence constituée de l'ascendance directe (que les parents, grands parents... racine), la fratrie , et la première génération suivante

    Pour schématiser, on va dire que je pars de cette arborescence (en rouge le noeud que je connais et qui doit servir de "carrefour")
    Code x : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ROOT
     ├─E1
     ├─E2
     │   ├─E21
     │   ├─E22
     │   │   ├─E221
     │   │   │   └─E2211
     │   │   └─E222
     │   └─E23
     │       └─E231
     └─E3

    Le résultat que je souhaite obtenir est le suivant:
    Code x : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ROOT
     └─E2
        ├─E21
        ├─E22
        │   ├─E221
        │   └─E222
        └─E23

    Je connais le noeud carrefour grace a la valeur d'un de ses attributs que je transmets à mon xsl

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <xsl:param name="req" />
    <xsl:variable name="vreq" select="//*[@name = $req]" />
    Je peux ainsi démarrer de mon noeud carrefour de la manière suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    <xsl:template match="/" >
    	<xsl:apply-templates select="$vreq" />
    </xsl:template>
    Si je fais comme ca, je ne sais pas comment faire pour remonter à la racine puis copier partiellement le xml en redescendant en ligne droite vers mon noeud carrefour...

    Je pense qu'une meilleure facon de faire serait de partir de la racine et de copier tous les noeuds qui répondent à une des conditions suivantes:
    - ce noeud est un ancêtre du noeud carrefour
    - ce noeud appartient à la fratrie du noeud carrefour
    - ce noeud est le noeud courant
    - ce noeud est un fils du noeud carrefour

    Cependant, je n'arrive pas à exprimer ces conditions à partir de ma variable...
    Et je n'arrive pas à saisir si cette expression doit apparaitre dans un test ou dans un select... (ni si cette question est pertinente...)

    J'aurais souhaité avoir votre avis sur la facon d'aborder le problème sachant que mes données initiales sont le xml (bien sur) et la valeur de l'attribut qui me permet de définir de manière unique mon noeud carrefour.

    Merci d'avance pour vos commentaires
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    N'oubliez pas de cliquer sur quand votre question à trouvé une solution.

    Si vous n'avez pas encore lu les règles du club, mieux vaut tard que jamais!

  2. #2
    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
    Bonjour,

    Citation Envoyé par MasterOfChakhaL
    Je pense qu'une meilleure facon de faire serait de partir de la racine et de copier tous les noeuds qui répondent à une des conditions suivantes:
    - ce noeud est un ancêtre du noeud carrefour
    - ce noeud appartient à la fratrie du noeud carrefour
    - ce noeud est le noeud courant
    - ce noeud est un fils du noeud carrefour
    C'est effectivement la bonne approche ; partir de ton élément $vreq serait assez compliqué, et peu performant.

    Ce cas de figure est assez facile à résoudre en utilisant des opérations ensemblistes. Le petit challenge est que cette recopie se fasse avec un parcours minimal de l'arbre. Ca peut se faire avec un seul template :
    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
     
    <xsl:template match="*">
      <xsl:choose>
        <xsl:when test="generate-id(.) = generate-id($vreq)">
          <!-- L'élément courant est vreq lui-même -->
          <xsl:copy>
            <!-- On recopie ses fils -->
            <xsl:for-each select="*">
              <xsl:copy/>
            </xsl:for-each>
          </xsl:copy>
        </xsl:when>
        <xsl:when test="count($vreq/ancestor::*|.) = count($vreq/ancestor::*)">
          <!-- l'élément courant est un ancètre de vreq, on le recopie -->
          <xsl:copy>
            <xsl:apply-templates select="*"/>
          </xsl:copy>
        </xsl:when>
        <xsl:when test="count($vreq/following-sibling::*|.) = count($vreq/following-sibling::*) or count($vreq/preceding-sibling::*|.) = count($vreq/preceding-sibling::*)">
          <!-- L'élément courant fait partie de la fratrie de vreq, on le recopie -->
          <xsl:copy/>
        </xsl:when>
      </xsl:choose>
    </xsl:template>
    Il faudra sans doute que tu ajoutes un peu de code pour recopier les éventuels attributs et noeuds textuels, mais le principe est là.
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

  3. #3
    Rédacteur
    Avatar de MasterOfChakhaL
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2004
    Messages
    2 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 147
    Points : 3 264
    Points
    3 264
    Par défaut
    Je te remercie de ton aide, le parcours correspond bel et bien a ce que je voulais!

    J'étais complétement passé à côté des generate-id, je pense que je lutterais moins à l'avenir...

    Un grand merci!!!
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    N'oubliez pas de cliquer sur quand votre question à trouvé une solution.

    Si vous n'avez pas encore lu les règles du club, mieux vaut tard que jamais!

  4. #4
    Rédacteur
    Avatar de MasterOfChakhaL
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2004
    Messages
    2 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 147
    Points : 3 264
    Points
    3 264
    Par défaut
    Pour compléter la solution proposée...

    Dans ton code, tu recopies les fils quand tu matches le noeud carrefour

    J'ai préféré faire une détection des fils sur le même modèle que les ancêtres et les frères.
    Je crois pas que ca change grand chose (peut-être une perte de performance car il y a des conditions en plus à tester) mais je trouve que c'est plus lisible...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <xsl:when test="count($vreq/descendant::*|.) = count( $vreq/descendant::*) and count(./ancestor::*) - count($vreq/ancestor::*) &lt;= 1">
    	<!-- L'élément courant fait partie de la descendant de vreq, on le recopie -->
    	<xsl:copy>
    		<xsl:apply-templates select="*" />
    	</xsl:copy>
    </xsl:when>
    Cette condition permet en plus de choisir la profondeur à laquelle on souhaite effectuer la recopie en modifiant le deuxième terme de l'inégalité (c'est vrai que ca ne faisait pas partie de la demande initiale)

    Une fois de plus, encore merci, je sens que j'ai franchi un pallier dans l'apprentissage de cette techno, ca fait toujours plaisir (même si mes efforts ne sont surement pas finis...)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    N'oubliez pas de cliquer sur quand votre question à trouvé une solution.

    Si vous n'avez pas encore lu les règles du club, mieux vaut tard que jamais!

  5. #5
    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
    Citation Envoyé par MasterOfChakhaL
    J'ai préféré faire une détection des fils sur le même modèle que les ancêtres et les frères.

    Cette condition permet en plus de choisir la profondeur à laquelle on souhaite effectuer la recopie en modifiant le deuxième terme de l'inégalité (c'est vrai que ca ne faisait pas partie de la demande initiale)
    C'est vrai que ça fait un code plus uniforme.

    Je te propose une variante plus simple de ton test de profondeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <xsl:when test="count(ancestor::*[position() &lt; 3]|$vreq) = count(ancestor::*[position() &lt; 3])">
      <!-- L'élément courant fait partie de la descendance de vreq jusqu'au 3ème degré, on le recopie -->  
      <xsl:copy>
        <xsl:apply-templates select="*"/>
      </xsl:copy>
    </xsl:when>
    Citation Envoyé par MasterOfChakhaL
    Une fois de plus, encore merci, je sens que j'ai franchi un pallier dans l'apprentissage de cette techno, ca fait toujours plaisir (même si mes efforts ne sont surement pas finis...)
    Je t'en prie.

    Une fois que tu maîtrises XPath (notamment ces tests de partitionnement), le reste de XSLT c'est du gateau...
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

  6. #6
    Rédacteur
    Avatar de MasterOfChakhaL
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2004
    Messages
    2 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 147
    Points : 3 264
    Points
    3 264
    Par défaut
    Effectivement, c'est bien plus simple ainsi, j'en déduis que ca doit également être plus performant du coup...

    Une fois que tu maîtrises XPath (notamment ces tests de partitionnement), le reste de XSLT c'est du gateau...
    Il doit bien y avoir quelques autres aspects subtiles mais je me disais bien que la maîtrise de Xpath avait l'air primordial...

    Merci, maintenant, je ne vais plus avoir de complexe à nommer mon xsl xml_optimize.xsl
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    N'oubliez pas de cliquer sur quand votre question à trouvé une solution.

    Si vous n'avez pas encore lu les règles du club, mieux vaut tard que jamais!

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 06/06/2011, 12h56
  2. Update or insert avec conditions sur les champs
    Par calou_33 dans le forum SQL
    Réponses: 7
    Dernier message: 04/08/2010, 10h36
  3. Réponses: 8
    Dernier message: 12/07/2008, 12h29
  4. Paginate avec des conditions sur les clés etrangères.
    Par CeDRiC08 dans le forum Ruby on Rails
    Réponses: 3
    Dernier message: 03/07/2007, 09h49
  5. [XPath] test d'existence de noeud avec conditions sur les enfants
    Par MasterOfChakhaL dans le forum XSL/XSLT/XPATH
    Réponses: 6
    Dernier message: 11/04/2007, 10h42

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