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] Rowspan vers multiples td


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Candidat au Club
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 3
    Points
    3
    Par défaut [XSLT] Rowspan vers multiples td
    Bonjour,

    J'ai à ma disposition des données en xml ordonnées en tableaux. Je dois proposer un document html et un document csv contenant les valeurs des tableaux et j'utilise pour cela xslt.

    les tableaux sont de la forme <table><tr><td></td></tr></table> comme en html, les td peuvent porter un attribut rowspan ou colspan.

    Aucun problème pour l'html, un seul pour le csv : les rowspan.

    Je souhaite convertir les rowspan en autant de td dans les tr suivants à la même position que le td en cours d'analyse (peut être dans une feuille xslt intermédiaire) avant de convertir le tout en csv.

    un exemple sera plus parlant :

    mon tableau original :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    +---+---+---+
    |   | 2 | 3 |
    | 1 +---+---+
    |   |   |   |
    +---+ 4 | 5 |
    | 6 |   |   |
    +---+---+---+
    Mon tableau transformé (souhaité)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    +---+---+---+
    | 1 | 2 | 3 |
    +---+---+---+
    | 1 | 4 | 5 |
    +---+---+---+
    | 6 | 4 | 5 |
    +---+---+---+
    voici comment j'ai traité le cas beaucoup plus simple des colspan :

    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
     
    <xsl:template match="td">
    	<xsl:variable name="contenu" select="."/>
    	<xsl:variable name="colspan" select="@colspan"/>
        <xsl:choose>
        	<xsl:when test="$colspan &gt; 0">
                <xsl:call-template name="Colspan">
                    <xsl:with-param name="nombre" select="$colspan"/>
                    <xsl:with-param name="compteur" select="0"/>
                    <xsl:with-param name="valeur" select="$contenu"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
       	     <td><xsl:value-of select="normalize-space($contenu)" /></td>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
     
    <xsl:template name="Colspan">
        <xsl:param name="nombre"/>
        <xsl:param name="compteur"/>
        <xsl:param name="valeur"/>
        <xsl:if test="$compteur &lt; $nombre">
        	<td><xsl:value-of select="normalize-space($valeur)" /></td>
            <xsl:call-template name="Colspan">
                <xsl:with-param name="nombre" select="number($nombre)"/>
                <xsl:with-param name="compteur" select="number($compteur)+1"/>
                <xsl:with-param name="valeur" select="$valeur"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
    Ce qui pose le + de souci étant que le nombre de lignes et de colonnes des différents tableaux n'est pas fixe et que je souhaiterais traiter ce cas d'une manière générique : n'importe quel nombre de <td rowspan="x"> par <tr> à n'importe quel endroit de ceux-ci. Il n'y a pas de règle du genre "seule la première case de la ligne peut comporter un rowspan".

    J'ai essayé de m'expliquer clairement je ne sais si c'est réussi mais y a un joli dessin.

    Merci pour votre aide.

  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,

    c'est un des cas où la nature profondément récursive et fonctionnelle de XSLT est plus un handicap qu'un atout par rapport à d'autres langages ; en Java par exemple, la solution est triviale : on parcourt une première fois le tableau pour déterminer le nombre total de lignes et de cellules, et on crée une matrice correspondante. On parcourt une deuxième fois le tableau et on alimente la matrice avec les valeurs lues, en tenant compte des rowspan et des colspan, et en sautant les cellules de la matrices déjà alimentées par une itération précédente.

    Il faut utiliser le même genre d'algorithme, mais la matrice doit être « émulée » par les appels récursifs aux templates. Joli casse-tête.
    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
    Candidat au Club
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Merci pour cette réponse,

    j'ai moi aussi conclus que c'était un sacré casse tête. Pour le moment, et pour ne pas perdre trop de temps je prépare une moulinette en php pour remplacer les rowspan et colspan par autant de td au bons endroits à l'aide de DomDocument.

    Ensuite retour au xslt pour le csv avec une feuille de style beaucoup plus simple pour le coup

    Néanmoins la question de tout faire en xslt reste intéressante si le casse tête s'avère soluble.

  4. #4
    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 AurelienVT Voir le message
    Néanmoins la question de tout faire en xslt reste intéressante si le casse tête s'avère soluble.
    Oh, c'est tout à fait faisable et je m'y serais bien collé, mais écrire un algorithme en raisonnant par récurrence est un petit peu hard pour un retour de congés...

    En tout cas, si la solution XSLT n'est pas forcément évidente, il est certain que le code XSLT sera bien plus concis que celui d'un traitement intermédiaire en PHP/DOM (ou tout autre langage). Le problème est intéressant, et je vais m'y pencher (avis aux amateurs).
    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

  5. #5
    Candidat au Club
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Pour ma part la moulinette DOM est terminée, et fonctionne très bien. Lorsque mon outil sera terminé et proportionnellement au temps qu'il me restera je me pencherai sur ce fameux problème, bien que mes capacités xslt soient assez limitées, ce site propose d'assez bon tutoriels

  6. #6
    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
    ma participation.
    Je ne trouve pas cela très élégant (cela serait déjà mieux en xslt 2.0...) mais cela à l'air de fonctionner

    fichier de travail:
    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
    <?xml version="1.0" encoding="UTF-8"?>
    <table>
    	<tr>
    		<td rowspan="2">1</td>
    		<td>2</td>
    		<td>3</td>
    	</tr>
    	<tr>
    		<td rowspan="2">4</td>
    		<td rowspan="2">5</td>
    	</tr>
    	<tr>
    		<td>6</td>
    	</tr>
    </table>
    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
    17
    18
    <?xml version="1.0" encoding="UTF-8"?>
    <table>
    <tr>
    <td>1</td>
    <td>2</td>
    <td>3</td>
    </tr>
    <tr>
    <td>1</td>
    <td>4</td>
    <td>5</td>
    </tr>
    <tr>
    <td>6</td>
    <td>4</td>
    <td>5</td>
    </tr>
    </table>
    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
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    <?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="/">
    		<table>
    			<xsl:call-template name="ligne">
    				<xsl:with-param name="elt_a_parcourir" select="//tr"/>
    				<xsl:with-param name="ligne_creer" select="''"/>
    			</xsl:call-template>
    		</table>
    	</xsl:template>
    	<xsl:template name="ligne">
    		<xsl:param name="elt_a_parcourir"/>
    		<xsl:param name="ligne_creer"/>
    		<xsl:if test="$elt_a_parcourir">
    			<tr>
    				<xsl:call-template name="cellule">
    					<xsl:with-param name="cell_parcourir" select="$elt_a_parcourir[1]/td"/>
    					<xsl:with-param name="ligne_prec" select="$ligne_creer"/>
    				</xsl:call-template>
    			</tr>
    			<xsl:variable name="lc">
    				<xsl:call-template name="creer">
    					<xsl:with-param name="cell_parcourir" select="$elt_a_parcourir[1]/td"/>
    					<xsl:with-param name="ligne_prec" select="$ligne_creer"/>
    				</xsl:call-template>
    			</xsl:variable>
    			<xsl:call-template name="ligne">
    				<xsl:with-param name="elt_a_parcourir" select="$elt_a_parcourir[position()&gt;1]"/>
    				<xsl:with-param name="ligne_creer" select="$lc"/>
    			</xsl:call-template>
    		</xsl:if>
    	</xsl:template>
    	<xsl:template name="cellule">
    		<xsl:param name="cell_parcourir"/>
    		<xsl:param name="ligne_prec"/>
    		<xsl:variable name="span" select="substring-before($ligne_prec,':')"/>
    		<xsl:variable name="val" select="substring-before(substring-after($ligne_prec,':'),'/')"/>
    		<xsl:if test="$cell_parcourir or $ligne_prec">
    			<xsl:choose>
    				<xsl:when test="$span and $span&gt;1">
    					<td>
    						<xsl:value-of select="$val"/>
    					</td>
    					<xsl:call-template name="cellule">
    						<xsl:with-param name="cell_parcourir" select="$cell_parcourir"/>
    						<xsl:with-param name="ligne_prec" select="substring-after($ligne_prec,'/')"/>
    					</xsl:call-template>
    				</xsl:when>
    				<xsl:otherwise>
    					<td>
    						<xsl:value-of select="$cell_parcourir[1]"/>
    					</td>
    					<xsl:call-template name="cellule">
    						<xsl:with-param name="cell_parcourir" select="$cell_parcourir[position()&gt;1]"/>
    						<xsl:with-param name="ligne_prec" select="substring-after($ligne_prec,'/')"/>
    					</xsl:call-template>
    				</xsl:otherwise>
    			</xsl:choose>
    		</xsl:if>
    	</xsl:template>
    	<xsl:template name="creer">
    		<xsl:param name="cell_parcourir"/>
    		<xsl:param name="ligne_prec"/>
    		<xsl:variable name="span" select="substring-before($ligne_prec,':')"/>
    		<xsl:variable name="val" select="substring-before(substring-after($ligne_prec,':'),'/')"/>
    		<xsl:if test="$cell_parcourir or $ligne_prec">
    			<xsl:choose>
    				<xsl:when test="$span and $span&gt;1">
    					<xsl:value-of select="number($span)-1"/>:<xsl:value-of select="$val"/>/<xsl:call-template name="creer">
    						<xsl:with-param name="cell_parcourir" select="$cell_parcourir"/>
    						<xsl:with-param name="ligne_prec" select="substring-after($ligne_prec,'/')"/>
    					</xsl:call-template>
    				</xsl:when>
    				<xsl:otherwise>
    					<xsl:choose>
    						<xsl:when test="$cell_parcourir[1]/@rowspan">
    							<xsl:value-of select="$cell_parcourir[1]/@rowspan"/>:<xsl:value-of select="$cell_parcourir[1]"/>/</xsl:when>
    						<xsl:otherwise>1:<xsl:value-of select="$cell_parcourir[1]"/>/</xsl:otherwise>
    					</xsl:choose>
    					<xsl:call-template name="creer">
    						<xsl:with-param name="cell_parcourir" select="$cell_parcourir[position()&gt;1]"/>
    						<xsl:with-param name="ligne_prec" select="substring-after($ligne_prec,'/')"/>
    					</xsl:call-template>
    				</xsl:otherwise>
    			</xsl:choose>
    		</xsl:if>
    	</xsl:template>
    </xsl:stylesheet>

  7. #7
    Candidat au Club
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Merci pour ce travail, je l'ai mis à l'épreuve avec des tableaux complexes, il fonctionne à merveille. Je vais l'étudier pour comprendre la démarche.

  8. #8
    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
    L'idée principale de l'algo est assez simple.
    Je reprend la ligne précedente creer mais en diminuant les rowspan du nombre de ligne deja faite.
    pour la deuxième ligne de ce tableau c'est un peu comme si jécrivais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <tr>
                              <td rowspan="1">1</td>		
                              <td rowspan="2">4</td>
    		<td rowspan="2">5</td>
    	</tr>
    Quand je fais la troisième ligne, je relis celle-ci, la ligne 2, (enfin dans mon cas l' "image" que j'en ai fait ) et je vois:
    première cellule rowspan= 1
    Donc je recopie la première cellule trouver dans la 3ème ligne, puis je passe à la deuxième cellule de la ligne 2 .
    Rowspan > 1 , je recopie donc cette cellule en diminuant le rowspan etc...
    Dès que je trouve une cellule de ligne 2 avec un rowspan à 1, je reprend la cellule suivante de la ligne 3 et ainsi de suite.

  9. #9
    Futur Membre du Club
    Inscrit en
    Février 2010
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Février 2010
    Messages : 5
    Points : 6
    Points
    6
    Par défaut
    Bonjour,

    Tout d'abord, un GRAND merci ! ce bout de code est vraiment très utile !!!

    En revanche, je rencontre un problème lorsque j'associe des cellules en colspan et rowspan...

    Voici mon tableau original :
    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
    +----------------+------+-------------+
    |       L1C1     |      |   L1C4L1C5  |
    +----------------+ L2C3 +-------------+
    |  L2C1  | L2C2  |      | L2C4 | L2C5 |
    +--------+-------+------+------+------+
    |  L3C1  | L3C2  | L3C3 | L3C4 | L3C5 |
    +--------+-------+------+------+------+
    |        | L4C2  | L4C3 | L4C4 |      |
    +        +-------+------+------+      +
    |  L4C1  | L5C2  | L5C3 | L5C4 |      |
    +        +-------+------+------+      +
    |        | L6C2  | L6C3 | L6C4 | L4C5 |
    +--------+-------+------+------+      +
    |  L7C1  | L7C2  | L7C3 | L7C4 |      |
    +--------+-------+------+------+      +
    |  L8C1  |       | L8C3 | L8C4 |      |
    +--------+ L8C2  +------+------+------+
    |  L9C1  |       | L9C3 | L9C4 | L9C5 |
    +--------+-------+------+------+------+
    |  L10C1 | L10C2 | L10C3| L10C4| L10C5|
    +--------+-------+------+------+------+
    et voici le tableau produit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    +----------------+------+-------------+
    |       L1C1     | L2C3 |   L1C4L1C5  |
    +----------------+------+-------------+
    |  L2C1  | L2C3  | L2C2 | L2C4 | L2C5 |
    +--------+-------+------+------+------+
    [...] (le reste fonctionne bien :))
    
    Quelqu'un aurait-il une idée ?

    Par avance, merci de votre sollicitude...

Discussions similaires

  1. [XSLT] XML vers XML
    Par cydream dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 17/04/2007, 17h45
  2. [XSLT] XML vers HTML
    Par SONY30 dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 05/04/2007, 08h54
  3. [XSLT] GraphML vers SVG
    Par Nyphel dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 08/02/2007, 00h52
  4. [XSLT]XML vers tableau html
    Par lcdDEV dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 27/10/2006, 16h55
  5. [XSLT] XML vers XML
    Par ren0 dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 13/10/2004, 12h54

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