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 :

Transformer les noeuds enfants en attributs ( + nom attributs paramétrés )


Sujet :

XSL/XSLT/XPATH XML

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2004
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 15
    Par défaut Transformer les noeuds enfants en attributs ( + nom attributs paramétrés )
    Bonjour,

    je suis vraiment débutant en xlst, et je n'arrive pas à obtenir le résultat souhaiter. j ai beau chercherché, je ne vois pas.

    mon xml de départ :
    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
     
     <table>
        <row>
          <column></column>
          <column></column>
          <column></column>
          <column></column>
         </row>
        <row>
          <column></column>
          <column></column>
          <column></column>
          <column></column>
             </row>
        <row>
          <column>ID</column>
          <column>DATE_ID</column>
          <column>STATUS_ID</column>
          <column>TYPE</column>
             </row>
        <row Height="A">
          <column>909584</column>
          <column>02/04/13 -14:05</column>
          <column>5</column>
          <column>ESNAC</column>
              </row>
        <row Height="A">
          <column>909480</column>
          <column>02/04/13 -13:31</column>
          <column>5</column>
          <column>PRW</column>
             </row>
    </table>
    J'applique ce masque que j'ai adpaté en cherchant sur le forum
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    <?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="ISO-8859-1" indent="yes"/>
      <xsl:template match="row">
        <xsl:copy>
          <xsl:for-each select="*">
            <xsl:attribute name="{name()}">
              <xsl:value-of select="."/>
            </xsl:attribute>
          </xsl:for-each>
        </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>

    Mais ce ne marche pas ...
    je n'arrive pas à basculer la valeur de mes noeuds <column > dans des attributs.
    J'aimerais obtenir la chose suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    <table>
    			<row column="" column="" column="" column="" >
    			<row column="" column="" column="" column="" >
    			<row column="ID" column="DATE_ID" column="STATUS_ID" column="TYPE">
    			<row column="909584" column="02/04/13" column="5" column="ESNAC">
    			<row column="909480" column="02/04/13" column="5" column="PRW">
    </table>

    Dans un deuxième temps, ce que je souhaiterais
    c'est utiliser le 3ème row car il contient le nom de mes attributs.
    Et il faudrait aussi supprimer les deux premiers row qui sont vide.

    ce qui donnerait en sortie à partir de mon xml de départ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <table>
    			<row ID="909584" DATE_ID="02/04/13" STATUS_ID="5" TYPE="ESNAC">
    			<row ID="909480" DATE_ID="02/04/13" STATUS_ID="5" TYPE="PRW">
    </table>

    Merci d'avance pour toute contribution

  2. #2
    Membre Expert Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Par défaut
    j ai beau chercherché
    Ca, je crois bien et c'est très bien.
    <xsl:for-each select="*">
    <xsl:attribute name="{name()}">
    <xsl:value-of select="."/>
    </xsl:attribute>
    </xsl:for-each>
    Celà a pas mal de chance de réussir parce que au moins la condition cardinale que tout le nom doit réspecter sera satisfaite. Mais, il n'est tout de même pas toujours correct si les noms d'enfants se répétent. En tant qu'élément, il n'y a pas de problème, mais en tant qu'attribut, si.

    <row column="" column="" column="" column="" >
    Comme vous savez, ce n'est pas acceptable au sens que le xml résultant est ainsi mal-formé.

    Si vous voulez le text des enfants devient le nom d'attribut, il faut encore s'assurer avant de faire ce genre de choses que les textes ne se répetent pas; et puis, qu'ils soient capable d'être un nom d'après la spec de xml - ce qui est très hazardeux et risqué (comme il n'y a pas d'espace dedans, il ne commence pas par une numbre etc etc...)

    Supposons tout soit en place, ce xsl:for-each peut prendre une forme comme ça approximativement.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <xsl:for-each select="*">
        <xsl:attribute name="{translate(normalize-space(),' ','')}">
            <xsl:value-of select="."/>    <!-- ou quelque valeur à déterminer -->
        </xsl:attribute>
    </xsl:for-each>
    Voilà.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Février 2004
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 15
    Par défaut
    Bonjour,

    merci sincèrment pour ta réponse, c'est un vraiment un forum au top

    alors j'ai adapté mon masque , il fonctionne correctement mais avec l'exemple
    plus bas :
    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
     
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:template match="table">
        <table>
          <xsl:apply-templates/>
        </table>
      </xsl:template>
      <xsl:template match="row">
        <row>
          <xsl:for-each select="*">
            <xsl:attribute name="{name()}">
              <xsl:value-of select="text()"/>
            </xsl:attribute>
          </xsl:for-each>
        </row>
      </xsl:template>
    </xsl:stylesheet>
    donc avec cette exemple le masque fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    <table>
      <row>
        <SERIALNUMBER>something111</SERIALNUMBER>
        <LOCATION>somethingtttrere</LOCATION>
        <BARCODE>somethingzerzer</BARCODE>
      </row>
    </table>
    Par contre comme tu dis justement, le probleme, est que n'on peut avoir plusieurs attributs de même nom.


    Etant donnée que je ne sais pas comment faire pour renommer mes attributs
    avec le contenu des noeuds de la 3ème ligne.

    j'ai mis en place une fonction en C# qui manipule mon xml pour obtenir le résultat attendu.

    Dommage , je pense qu'un masque xlst aurait été plus performant.

    mais merci

    a+

  4. #4
    Membre Expert Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Par défaut
    Attendez. Je n'ai pas d'opinion (ou plutôt d'objection) pour une choice (c#) ou une autre: c'est une choice de chacun d'après multitude de facteurs à considérer.

    Mais si on se place comme un travailleur d'une technologie, on ne peut la démissioner sans étaler la possibilité.

    Le problème c'est qu'il faut générer les noms uniques pour les attributs sans sacrifice la liaison de leur origine. Pour ça le plus intuitive c'est de mettre un préfixe ou suffixe d'après la position de l'enfant en question: comme ça.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <xsl:template match="row">
        <xsl:copy>
            <xsl:for-each select="*">
                <xsl:attribute name="{concat(name(),'_',position())}">
                    <xsl:value-of select="normalize-space()"/>
                </xsl:attribute>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
    Une autre façon de le faire que je préfère pour la raison plus obscure est de utiliser leur id innée, une valeur qui dépend le moteur xslt, comme ça.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <xsl:template match="row">
        <xsl:copy>
            <xsl:for-each select="*">
                <xsl:attribute name="{concat(name(),'_',generate-id())}">
                    <xsl:value-of select="normalize-space()"/>
                </xsl:attribute>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
    C'est tout ce que j'ai à dire.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Février 2004
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 15
    Par défaut
    Merci bien pour ta réponse

    cette solution n'est pas encore suffisante ... car le nom des attributs est connu. Sur le 3ème noeud row, j'ai le nom des attributs :
    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
     
    <table>
        <row>
          <column></column>
          <column></column>
          <column></column>
          <column></column>
         </row>
        <row>
          <column></column>
          <column></column>
          <column></column>
          <column></column>
             </row>
        <row>
          <column>ID</column>
          <column>DATE_ID</column>
          <column>STATUS_ID</column>
          <column>TYPE</column>
             </row>
    ...

    donc si j'applique le masque , il doit encore après renommer chaque noeud d'attributs avec le nom issu du 3ème noeud row.

    ce que j'ai réussi à faire à C# mais ce que je ne sais pas faire en appliquant du xslt ...

    après il faudrait aussi , que je renomme un noeud, et aussi supprimer les lignes row vides ...

  6. #6
    Membre Expert Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Par défaut
    D'accord. Si spécialité emporte sur généralité, on peut s'accommoder et on ne se plainte pas une nombre magique comme 3.
    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
    <xsl:template match="table[count(row) &gt;= 3]">
        <xsl:copy>
            <xsl:apply-templates select="row[normalize-space()!='']" mode="special" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="row" mode="special">
        <xsl:choose>
            <xsl:when test="count(preceding-sibling::row)=2">
                <!-- ne rien faire -->
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:for-each select="column">
                        <xsl:variable name="p" select="position()" />
                        <xsl:choose>
                            <xsl:when test="normalize-space()=''">
                                <!-- ne rien faire -->
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:attribute name="{ancestor::table[1]/row[3]/column[$p]}">
                                    <xsl:value-of select="normalize-space()" />
                                </xsl:attribute>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:for-each>
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    Une fois on y arrive, on peut contempler de l'améliorer un peu.

Discussions similaires

  1. [XSD] noeuds enfants contextuels selon un attribut
    Par caballo dans le forum Valider
    Réponses: 7
    Dernier message: 12/05/2011, 14h30
  2. [SimpleXML] Afficher les noms de tous les noeuds enfants
    Par jminguely dans le forum Bibliothèques et frameworks
    Réponses: 5
    Dernier message: 22/05/2009, 09h44
  3. [XSLT] Regrouper les noeuds en fonction d'un attribut
    Par Creuvard dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 11/12/2008, 12h31
  4. [XSLT] Transformer les noeuds enfants en attribut du premier noeud
    Par le_chomeur dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 22/02/2008, 14h57
  5. Supprimer tous les noeuds enfants
    Par Givemefive dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 23/01/2007, 13h39

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