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 :

Convertion XML (structure)


Sujet :

XSL/XSLT/XPATH XML

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    infographiste
    Inscrit en
    Avril 2012
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : infographiste
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2012
    Messages : 41
    Par défaut Convertion XML (structure)
    Bonjour,

    Je suis depuis quelque jour sur XSLT et je rame!
    Voici mon problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?xml version="1.0" encoding="UTF-8"?>
    <CH>
        <SE_T>Titre <i>01</i></SE_T>
        <P>Para 01.1 <I>1</I></P>
        <P>Para 01.2 <I>2</I></P>
        <P>Para 01.3 <I>3</I></P>
        <SE_T>Titre <i>02</i></SE_T>
        <P>Para 02.1 <I>1</I></P>
        <CI>Cit <it>01</it></CI>
        <CI>Cit <it>01</it></CI>
        <P>Para 02.2 <I>1</I></P>
    </CH>
    je voudrais arriver à sa :
    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
    <?xml version="1.0" encoding="UTF-8"?>
    <CH>
        <SE>
            <T>Titre <i>01</i></T>
            <P>Para 01.1 <I>1</I></P>
            <P>Para 01.2 <I>2</I></P>
            <P>Para 01.3 <I>3</I></P>
        </SE>
        <SE>
            <T>Titre <i>02</i></T>
            <P>Para 02.1 <I>1</I></P>
            <CI>
                <P>Cit <it>01</it></P>
                <P>Cit <it>01</it></P>
            </CI>
            <P>Para 02.2 <I>1</I></P>
        </SE>
    </CH>
    le mieux (entre autre), que j'ai réussi à avoir c'est plus ou mois ç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
    <?xml version="1.0" encoding="UTF-8"?>
    <SE><T>Titre <i>01</i></T>
        <P>Para 01.1 1</P>
        <P>Para 01.2 2</P>
        <P>Para 01.3 3</P>
        <P>Titre 02</P>
        <P>Para 02.1 1</P>
        <P>Cit 01</P>
        <P>Cit 01</P>
        <P>Para 02.2 1</P>
    </SE>
     
    <SE><T>Titre <i>02</i></T>
        <P>Para 01.1 1</P>
        <P>Para 01.2 2</P>
        <P>Para 01.3 3</P>
        <P>Titre 02</P>
        <P>Para 02.1 1</P>
        <P>Cit 01</P>
        <P>Cit 01</P>
        <P>Para 02.2 1</P>
    </SE>
     
    Cit 01
    Cit 01
    Voici un des codes XSLT :
    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
     
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     
        <xsl:template match="SE_T">
            <SE>
                <T>
                    <xsl:for-each select="*[name()!='SE_T']|text()">
                        <xsl:copy-of select="." />
                    </xsl:for-each>
                </T>
                <xsl:for-each select="//SE_T/following-sibling::*">
     
                    <xsl:choose>
                        <xsl:when test="*[name()='P']">
     
                            <P>
                                <xsl:for-each select="*[name()!='P']|text()">
                                    <xsl:copy-of select="." />
                                </xsl:for-each>
                            </P>
     
                         <xsl:for-each select="//following-sibling::*[name()!='P']|text()">
                                <xsl:copy-of select="."/>
                            </xsl:for-each>
     
                        </xsl:when>
                       <xsl:when test="//following-sibling::*[name()='P']">
                            <P>
                                <xsl:for-each select="*[name()!='P']|text()">
                                    <xsl:value-of select="." />
                                </xsl:for-each>
                            </P>
                        </xsl:when>
                        <xsl:when test="//following-sibling::*[name()='CI']">
                            <CI>
                                <P>
                                    <xsl:for-each select="*[name()!='CI']|text()">
                                        <xsl:value-of select="." />
                                    </xsl:for-each>
                                </P>
                            </CI>
                        </xsl:when>
                    </xsl:choose>
                </xsl:for-each>
            </SE>
        </xsl:template>
     
        <xsl:template match="P"/>
     
    </xsl:stylesheet>
    Merci si quelqu'un pouvais me donner une piste !!!!

    Help!!!

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    C'est en fait assez compliqué. On va d'abord simplifier le problème : transformer les <SE_T> en <SE> qui entoure tout ce qu'il faut.

    Exemple simple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <root>
      <p>A.1</p>
      <z>A.2</z>
      <z>A.3</z>
      <p>B.1</p>
      <z>B.2</z>
    </root>
    à transformer en :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <root>
      <p>
        <z>A.1</z>
        <z>A.2</z>
        <z>A.3</z>
      </p>
      <p>
        <z>B.1</z>
        <z>B.2</z>
      </p>
    </root>
    On fait comme ç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
    <xsl:template match="root">
      <!-- La racine, elle change pas -->
      <root>
        <!-- On ne regarde que les <p>, c'est eux qui regroupent -->
        <xsl:apply-templates select="p"/>
      </root>
    </xsl:template>
     
    <xsl:template match="p">
      <p>
        <z><xsl:apply-templates/></z>
        <!-- garder l'id du <p> en cours -->
        <xsl:variable name="id" select="generate-id(.)"/>
        <!-- pour tout ce qu'il y a ensuite -->
        <xsl:for-each select="following-sibling::z">
          <!-- récupérer quel est son premier <p> précédent -->
          <xsl:variable name="predP" select="preceding-sibling::p[1]"/>
          <!-- si le <p> précédent est le même <p> que le <p> en cours -->
          <xsl:if test="generate-id($predP) = $id">
            <xsl:apply-templates select="."/>
          </xsl:if>
        </xsl:for-each>
      </p>
    </xsl:template>
     
    <!-- et ça c'est tout simple -->
    <xsl:template match="z">
       <z><xsl:apply-templates/></z>
    </xsl:template>
    Bref c'est la chiotte pour trouver les éléments encadrés entre deux <p>, mais on y arrive.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre averti
    Homme Profil pro
    infographiste
    Inscrit en
    Avril 2012
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : infographiste
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2012
    Messages : 41
    Par défaut
    Merci mais une chiotte c'est peux dire pour commencer en xslt, il y a plus simple....

    J' ai transformé le code pour mes balise cela fonction le voici :
    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
    <?xml version="1.0" encoding="UTF-8"?>    
        <xsl:template match="CH">
            <!-- La racine, elle change pas -->
            <CH>
                <!-- On ne regarde que les <SE_T>, c'est eux qui regroupent -->
                <xsl:apply-templates select="SE_T"/>
            </CH>
        </xsl:template>
     
        <xsl:template match="SE_T">
            <SE>
              <!-- <T><xsl:apply-templates/></T>-->
                <T><xsl:for-each select="*[name()!='SE_T']|text()"><xsl:copy-of select="." /></xsl:for-each></T>
                <!-- garder l'id du <SE_T> en cours -->
                 <xsl:variable name="id" select="generate-id(.)"/>
                 <!-- pour tout ce qu'il y a ensuite -->
                 <xsl:for-each select="following-sibling::P">
                     <!-- récupérer quel est son premier <p> précédent -->
                     <xsl:variable name="predP" select="preceding-sibling::SE_T[1]"/>
                     <!-- si le <SE_T> précédent est le même <SE_T> que le <SE_T> en cours -->
                     <xsl:if test="generate-id($predP) = $id">
                         <xsl:apply-templates select="."/>
                     </xsl:if>
                 </xsl:for-each>
            </SE>
        </xsl:template>
     
        <!-- et ça c'est tout simple -->
        <xsl:template match="P">
            <P><xsl:for-each select="*[name()!='P']|text()"><xsl:copy-of select="." /></xsl:for-each></P>
        </xsl:template>
     
    </xsl:stylesheet>
    Mais il faut encore compliqué la chose :
    code xml de départ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <root>
        <p>A.1</p>
        <z>A.2</z>
        <z>A.3</z>
        <p>B.1</p>
        <z>B.2</z>
        <c>B.3</c>
        <c>B.4</c>
        <z>B.5</z>
    </root>
    Code XML à la sortie :
    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
    <root>
        <p>
            <z>A.1</z>
            <z>A.2</z>
            <z>A.3</z>
        </p>
        <p>
            <z>B.1</z>
            <z>B.2</z>
            <c>
                <z>B.3</z>
                <z>B.4</z>
            </c>
            <z>B.5</z>
        </p>
    </root>
    Tous est pratiquement au même niveaux et là c'est compliqué avec XSLT (je croix), l'XSLT est-il ce qu'il me faut???

    Mais merci thelvin

  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
    Je ne suis pas très convincu toutes les règles sont bien et exhaustivement conçues. J'espère les abstractions sont faites judicieusement parce que ce n'est pas tout à fait évident pour un non-expérimenté, même des expérimentés, de réussi à exhibiter tous les caractères génerique dans une version d'abstraction. En tout cas, avançons...

    Voici une version qui fait appel aux moyens élémentaires et c'est important d'arriver un résultat correct avant de faire des sophistications avec des moyens comme xsl:key et quoi d'autres...
    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
    <xsl:template match="CH">
        <xsl:copy>
            <xsl:apply-templates select="SE_T" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="SE_T">
        <SE>
            <T><xsl:copy-of select="*|text()" /></T>
            <xsl:variable name="c" select="count(following-sibling::*)" />
            <xsl:variable name="p" select="count(following-sibling::SE_T[1]/following-sibling::*)" />
            <xsl:for-each select="following-sibling::*[position() &gt; 0 and position() &lt; ($c - $p + 1)]">
                <xsl:choose>
                    <xsl:when test="name()='P'">
                        <xsl:copy-of select="." />
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:if test="name()!=name(preceding-sibling::*[1])">
                            <xsl:copy>
                                <xsl:call-template name="consolidate">
                                    <xsl:with-param name="ctx" select="." />
                                    <xsl:with-param name="name" select="name()" />
                                </xsl:call-template>
                            </xsl:copy>
                        </xsl:if>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
        </SE>
    </xsl:template>
    <xsl:template name="consolidate">
        <xsl:param name="ctx" />
        <xsl:param name="name" />
        <xsl:if test="name($ctx)=$name">
        <P><xsl:copy-of select="*|text()" /></P>
        <xsl:call-template name="consolidate">
            <xsl:with-param name="ctx" select="$ctx/following-sibling::*[1]" />
            <xsl:with-param name="name" select="$name" />
        </xsl:call-template>
        </xsl:if>
    </xsl:template>

  5. #5
    Membre averti
    Homme Profil pro
    infographiste
    Inscrit en
    Avril 2012
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : infographiste
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2012
    Messages : 41
    Par défaut
    Bonjour tsuji,

    Merci pour le code, j'ai testé fais une petit motif.

    Voici exemple de 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
    <?xml version="1.0" encoding="UTF-8"?>
    <CH>
        <SE_T>Titre <i>01</i></SE_T>
        <P>Para 01.1 <I>1</I></P>
        <P>Para 01.2 <I>2</I></P>
        <P>Para 01.3 <I>3</I></P>
        <SE_T>Titre <i>02</i></SE_T>
        <P>Para 02.1 <I>1</I></P>
        <CI>Cit <it>01</it></CI>
        <CI>Cit <it>01</it></CI>
        <P>Para 02.2 <I>1</I></P>
    </CH>
    J'ai modifié la ligne suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     <xsl:for-each select="following-sibling::*[position() &gt; 0 and position() &lt; ($c - $p + 1) and name() != 'SE_T']">
    avec cet ajoute et le résulta est :
    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"?>
    <CH>
       <SE>
          <T>Titre <i>01</i>
          </T>
          <P>Para 01.1 <I>1</I>
          </P>
          <P>Para 01.2 <I>2</I>
          </P>
          <P>Para 01.3 <I>3</I>
          </P>
       </SE>
       <SE>
          <T>Titre <i>02</i>
          </T>
          <P>Para 02.1 <I>1</I>
          </P>
          <CI>
             <P>Cit <it>01</it>
             </P>
             <P>Cit <it>01</it>
             </P>
          </CI>
          <P>Para 02.2 <I>1</I>
          </P>
       </SE>
    </CH>
    je vais intégré ce code avec les autres et passé à la suite!

    Merci

  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
    Bonjour liphou,
    J'ai modifié la ligne suivante :
    <xsl:for-each select="following-sibling::*[position() &gt; 0 and position() &lt; ($c - $p + 1) and name() != 'SE_T']">
    avec cet ajoute
    name() != 'SE_T'
    Ce n'est pas nécessaire parce que cette condition est déjà tenue compte dans la définition de $p, donc, il n'y a déjà pas de balise SE_T dans l'ensemble de noeuds sélectionné sans elle.

  7. #7
    Membre averti
    Homme Profil pro
    infographiste
    Inscrit en
    Avril 2012
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : infographiste
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2012
    Messages : 41
    Par défaut
    Si je fais sans cet ragoute j’obtiens ce si :
    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
     
    <CH>
       <SE>
          <T>Titre <i>01</i>
          </T>
          <P>Para 01.1 <I>1</I>
          </P>
          <P>Para 01.2 <I>2</I>
          </P>
          <P>Para 01.3 <I>3</I>
          </P>
          <SE_T>
             <P>Titre <i>02</i>
             </P>
          </SE_T>
       </SE>
       <SE>
          <T>Titre <i>02</i>
          </T>
          <P>Para 02.1 <I>1</I>
          </P>
          <CI>
             <P>Cit <it>01</it>
             </P>
             <P>Cit <it>01</it>
             </P>
          </CI>
          <P>Para 02.2 <I>1</I>
          </P>
       </SE>
    </CH>
    J'ai une répétition du
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <SE_T>
             <P>Titre <i>02</i>
             </P>
          </SE_T>
    Je continue à regardé le code pour le connaitre et le maitrisé,
    je vais l'intégré dans mon filtre globale.

    Merci

  8. #8
    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
    Oui, j'ai mis la formule incorrecte par un numbre 1. Ce ligne#11
    <xsl:for-each select="following-sibling::*[position() &gt; 0 and position() &lt; ($c - $p + 1)]">
    doit se lire comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:for-each select="following-sibling::*[position() &gt; 0 and position() &lt; ($c - $p)]">
    Mais pour arriver l'arithemetic correcte, il y a une correction sur la formula de p quand il n'y a plus following-sibling::SE_T (quelle confusion, pardon!) Au lieu de ça
    <xsl:variable name="p" select="count(following-sibling::SE_T[1]/following-sibling::*)" />
    je dois l'écrire comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <xsl:variable name="p">
        <xsl:if test="following-sibling::SE_T">
            <xsl:value-of select="count(following-sibling::SE_T[1]/following-sibling::*)" />
        </xsl:if>
        <xsl:if test="not(following-sibling::SE_T)">
            <xsl:value-of select="-1" />
        </xsl:if>
    </xsl:variable>
    Voilà la version entière révisée d'après cela pour éviter tout malentendu.
    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
    <xsl:template match="CH">
        <xsl:copy>
            <xsl:apply-templates select="SE_T" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="SE_T">
        <SE>
            <T><xsl:copy-of select="*|text()" /></T>
            <xsl:variable name="c" select="count(following-sibling::*)" />
            <xsl:variable name="p">
                <xsl:if test="following-sibling::SE_T">
                    <xsl:value-of select="count(following-sibling::SE_T[1]/following-sibling::*)" />
                </xsl:if>
                <xsl:if test="not(following-sibling::SE_T)">
                    <xsl:value-of select="-1" />
                </xsl:if>
            </xsl:variable>
            <xsl:for-each select="following-sibling::*[position() &gt; 0 and position() &lt; ($c - $p)]">
                <xsl:choose>
                    <xsl:when test="name()='P'">
                        <xsl:copy-of select="." />
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:if test="name()!=name(preceding-sibling::*[1])">
                            <xsl:copy>
                                <xsl:call-template name="consolidate">
                                    <xsl:with-param name="ctx" select="." />
                                    <xsl:with-param name="name" select="name()" />
                                </xsl:call-template>
                            </xsl:copy>
                        </xsl:if>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
        </SE>
    </xsl:template>
    <xsl:template name="consolidate">
        <xsl:param name="ctx" />
        <xsl:param name="name" />
        <xsl:if test="name($ctx)=$name">
            <P><xsl:copy-of select="*|text()" /></P>
            <xsl:call-template name="consolidate">
                <xsl:with-param name="ctx" select="$ctx/following-sibling::*[1]" />
                <xsl:with-param name="name" select="$name" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
    ps: Je dois mettre au point cette correction en deux temps pour arriver ça et j'espère je peux la mettre une pointe finale.

Discussions similaires

  1. [XSLT] Convertion XML en WBXML
    Par wisstr dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 02/08/2006, 11h37
  2. Réponses: 6
    Dernier message: 21/07/2006, 09h18
  3. [XML] Structure de fichier
    Par LE NEINDRE dans le forum XML/XSL et SOAP
    Réponses: 6
    Dernier message: 15/06/2006, 18h25
  4. Font , Xml & structure de programme .
    Par Clad3 dans le forum XML
    Réponses: 11
    Dernier message: 30/03/2005, 22h45
  5. [C#] Convertion de structure vers Delphi .NET
    Par Laurent Dardenne dans le forum Windows Forms
    Réponses: 21
    Dernier message: 08/01/2005, 02h36

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