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 :

Faire un joli tableau HTML d'un XML via XSL


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 7
    Points : 5
    Points
    5
    Par défaut Faire un joli tableau HTML d'un XML via XSL
    Bonjour,

    je reviens vers ce forum malgré que mon dernier post n'est pas interessé grand monde voir personne ^^

    l'idée est donc de transformer un XML récuperé sur le web en un joli tableau présentant les informations de maniere ordonnée.

    Aujourd'hui je parviens à obtenir le résultat attendu avec le XSL que j'ai fait
    Me reste un gros problème, la génération HTML peut être tres (voir trop) longue avec un XML de taille importante et je ne sais pas comment optimiser mon code ...

    voici un exemple de XML
    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" encoding="UTF-8"?>
    <?xml-stylesheet type="text/xsl" href="park.xsl" ?>
    <park id="50">
    	<x>40</x> <!-- Largeur du park, nombre de colonne -->
    	<y>50</y> <!-- Hauteur du park, nombre de ligne -->
    <!-- on doit générer un tableau sus cette forme
           1  2  3  ...  40 (=x)
    50   X
    49          O
    ...
    1
    (=y)
    -->
    <!-- Le fichier XML en entrée est trié sur les Positions x (colonnes) à partir de 1, et y (lignes) à partir de 1
    Il faudra donc retrié le xml sur y descendant (à partir de 50) et x ascendant -->
    	<nom>Parking numero 50</nom>
    	<pos x="1" y="1">		<!-- x=Position colonne, y=Position ligne -->
    		<vehicule id="1238">
    			<marque>peugeot</marque>
    			<type>407</type>
    			<chevaux>7</chevaux>
    		</vehicule>
    	</pos>
    	<pos x="4" y="10" bloque="O"/>
    	<pos x="5" y="23" bloque="O"/>
    	<pos x="6" y="31" bloque="O"/>
    	<pos x="15" y="1">
    		<vehicule id="1234">
    			<marque>peugeot</marque>
    			<type>305</type>
    			<chevaux>5</chevaux>
    		</vehicule>
    	</pos>
    	<pos x="18" y="10" bloque="O"/>
    	<pos x="23" y="5" bloque="O"/>
    	<pos x="25" y="33">
    		<vehicule id="4321">
    			<marque>renault</marque>
    			<type>clio</type>
    			<chevaux>4</chevaux>
    		</vehicule>
    	</pos>
    	<pos x="38" y="1">
    		<vehicule id="1235">
    			<marque>peugeot</marque>
    			<type>106</type>
    			<chevaux>4</chevaux>
    		</vehicule>
    	</pos>
    </park>
    Voici le XSL que j'ai fait pour afficher les infos sous la forme attendue
    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
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
     
    <?xml version="1.0" encoding="iso-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    	<xsl:template match="/">
    		<html>
    			<head>
    			</head>
    			<body>
    				<xsl:for-each select="park">
    					<xsl:sort select="pos/@y" data-type="number" order="descending"/>
    						<xsl:sort select="pos/@x" data-type="number" order="ascending"/> 
    					<tr>
    						<td valign="top"><font face="arial"><xsl:value-of select="concat(@id,' ',nom)" /></font></td>
    					</tr>
    					<table border="1">
    						<tr valign="bottom">
    							<td align="right"><font face="arial"></font></td>
    							<!-- PREMIERE BOUCLE: Fixer les numeros (1 à x) en 1ere ligne  -->
    							<xsl:call-template name="ligne1">
    								<xsl:with-param name="compteur" select="1" />
    								<xsl:with-param name="finboucle" select="x" />
    							</xsl:call-template>
    						</tr>
    						<!-- DEUXIEME BOUCLE: pour i=1 a Nombre de ligne (y) -->
    						<xsl:call-template name="lignes">
    							<xsl:with-param name="compteur" select="y" />
    							<xsl:with-param name="finboucle" select="1" />
    						</xsl:call-template>
    					</table>
    				</xsl:for-each>
    			</body>
    		</html>
    	</xsl:template>
     
    <!-- Première ligne, Numérotation -->	
    	<xsl:template name="ligne1">
    	 <xsl:param name="compteur" />
    	 <xsl:param name="finboucle" />
    	 <xsl:choose>
    	  <xsl:when test="$compteur &lt;= $finboucle">
    		<td align="right"><font face="arial"><xsl:value-of select="$compteur" /></font></td>
    		<xsl:call-template name="ligne1">
    			<xsl:with-param name="compteur" select="$compteur + 1" />
    			<xsl:with-param name="finboucle" select="$finboucle" />
    		</xsl:call-template>
    	  </xsl:when>
    	  <xsl:otherwise>
    	  </xsl:otherwise>
    	 </xsl:choose>
    	</xsl:template>
     
    <!-- Boucle sur le nombre de ligne  -->	
    	<xsl:template name="lignes">
    	 <xsl:param name="compteur" />
    	 <xsl:param name="finboucle" />
    	 <xsl:choose>
    	  <xsl:when test="$compteur &gt;= $finboucle">
    		<tr valign="bottom">
    			<!-- Numerotation de la ligne -->
    			<td align="right"><font face="arial"><xsl:value-of select="$compteur" /></font></td>
    			<!-- Génération de la ligne courante -->
    			<xsl:for-each select="pos[@y=$compteur]">
    				<xsl:variable name="PosX"><xsl:value-of select="@x" /></xsl:variable>
    				<xsl:variable name="xPrec"><xsl:value-of select="number(/park/pos[@y = $compteur and @x &lt; $PosX][last()]/@x)" /></xsl:variable> 
    				<!-- Faire le complement colonne a gauche -->
    				<xsl:choose>
    					<xsl:when test="$xPrec = 'NaN'">
    						<xsl:call-template name="lignevide">
    							<xsl:with-param name="compteur" select="1" />
    							<xsl:with-param name="finboucle" select="number(@x) - 1" />
    						</xsl:call-template>
    					</xsl:when>
    					<xsl:otherwise>
    						<xsl:call-template name="lignevide">
    							<xsl:with-param name="compteur" select="number($xPrec) + 1" />
    							<xsl:with-param name="finboucle" select="number(@x) - 1" />
    						</xsl:call-template>
    					</xsl:otherwise>
    				</xsl:choose>
    				<!-- on traite la colonne en cours -->
    				<xsl:choose>
    					<xsl:when test="@bloque = 'O'">
    						<!-- PLACE INOCCUPABLE -->
    						<td align="center"><font face="arial" color="#000000">X</font></td>
    					</xsl:when>
    					<xsl:otherwise>
    						<!-- PLACE OCCUPEE -->
    						<xsl:variable name="Infos">Id:<xsl:value-of select="vehicule/@id" /> (<xsl:value-of select="vehicule/marque" /> - <xsl:value-of select="vehicule/type" /> - <xsl:value-of select="vehicule/chevaux" /> - <xsl:value-of select="@x" />/<xsl:value-of select="@y" />)</xsl:variable>
    						<xsl:variable name="Lien">window.open('../infopark.php?id=<xsl:value-of select="vehicule/@id"/>','vehicule_Stat','height=350, width=390, scrollbars=1, status=0, toolbar=0, menubar=0');</xsl:variable>
    						<td valign="center">
    							<xsl:attribute name="title"><xsl:value-of select="$Infos" /></xsl:attribute>
    							<xsl:attribute name="onclick"><xsl:value-of select="$Lien"/></xsl:attribute>
    							<font face="arial" color="#FF0000">O</font>
    						</td>
    					</xsl:otherwise>
    				</xsl:choose>
    				<!-- Faire le complement colonne a droite -->
    				<xsl:variable name="xSuite"><xsl:value-of select="number(/park/pos[@y = $compteur and @x &gt; $PosX]/@x)" /></xsl:variable> 
    				<xsl:choose>
    					<xsl:when test="$xSuite = 'NaN'">
    						<xsl:call-template name="lignevide">
    							<xsl:with-param name="compteur" select="number(@x) + 1" />
    							<xsl:with-param name="finboucle" select="/park/x" />
    						</xsl:call-template>
    					</xsl:when>
    				</xsl:choose>
    			</xsl:for-each>
    		</tr>
    		<xsl:call-template name="lignes">
    			<xsl:with-param name="compteur" select="$compteur - 1" />
    			<xsl:with-param name="finboucle" select="$finboucle" />
    		</xsl:call-template>
    	  </xsl:when>
    	  <xsl:otherwise>
    	  </xsl:otherwise>
    	 </xsl:choose>
    	</xsl:template>
     
    <!-- Génération ligne vide -->	
    	<xsl:template name="lignevide">
    	 <xsl:param name="compteur" />
    	 <xsl:param name="finboucle" />
    	 <xsl:choose>
    	  <xsl:when test="$compteur &lt;= $finboucle">
    		<td align="right"><font face="arial"> </font></td>
    		<xsl:call-template name="lignevide">
    			<xsl:with-param name="compteur" select="$compteur + 1" />
    			<xsl:with-param name="finboucle" select="$finboucle" />
    		</xsl:call-template>
    	  </xsl:when>
    	  <xsl:otherwise>
    	  </xsl:otherwise>
    	 </xsl:choose>
    	</xsl:template>
     
    </xsl:stylesheet>
    ce qui me pose le plus de souci, c'est la génération des colonnes complément à gauche et à droite, car j'ai besoin de connaitre pour ces traitements, les valeurs des enregistrements precedents et suivants
    voici le code xsl utilisé pour repondre à ce besoin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:variable name="xPrec"><xsl:value-of select="number(/park/pos[@y = $compteur and @x &lt; $PosX][last()]/@x)" /></xsl:variable>
    Ca me retourne la valeur de l'attribut x précédent, mais ca prend beaucoup de ressource, et ca se ressent sur un gros xml

    de meme pour la valeur suivante cette instruction est hyper gourmande:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:variable name="xSuite"><xsl:value-of select="number(/park/pos[@y = $compteur and @x &gt; $PosX]/@x)" /></xsl:variable>
    Comment optimiser tout ca ?
    voici le resultat attendu (sachant qu'il y a toujours au moins une information par ligne dans un XML normal):
    http://freddyp2.free.fr/XML/park.xml

  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,

    il y a beaucoup plus simple à faire...

    Déjà, indexer les éléments <pos> par leur attribut y :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:key name="positions" match="pos" use="@y"/>
    Le template d'affichage des cellules qui doit être appelé à chaque itération sur une ligne, sera celui-ci :
    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
    <xsl:template affiche-cellule">
      <xsl:param name="num-ligne"/>
      <xsl:param name="num-colonne" select="1"/>
      <xsl:param name="nombre-colonnes"/>
      <xsl:if test="$num-colonne &lt;= $nombre-colonnes">
        <xsl:variable name="cellule" select="key('positions', $num-ligne)[@x = $num-colonne]"/>
        <td>
          <xsl:choose>
            <xsl:when test="$cellule">
              <xsl:choose>
                <xsl:when test="@bloque = 'O'">O</xsl:when>
                <xsl:otherwise>
                   <!-- Affichage des infos de la voiture, grace à $cellule -->
                </xsl:otherwise>        
              </xsl:choose>
            </xsl:when>
            <xsl:otherwise>
              <xsl:text> </xsl:text>
            </xsl:otherwise>
          </xsl:choose>
        </td>
        <xsl:call-template name="affiche-cellule">
          <xsl:with-param name="num-ligne" select="$num-ligne"/>
          <xsl:with-param name="num-colonne" select="$num-colonne + 1"/>
          <xsl:with-param name="nombre-colonnes" select="$nombre-colonnes"/>
        </xsl:call-template>
      </xsl:if>
    </xsl:template>
    Du fait de l'utilisation de xsl:key, il n'y a pratiquement plus de parcours de l'arbre au cours de la construction du tableau. Il est possible d'alléger le template en déclarant $nombre-colonnes comme une variable globale, puisque qu'il n'y a qu'un seul tableau à afficher, mais c'est un détail...

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par GrandFather
    il y a beaucoup plus simple à faire...
    ça je n'en doutais pas un seul instant

    en tout cas un grand merci, ça marche impecc, et c'est tres rapide, meme sur un gros xml

    faut vraiment revoir sa methode de programmation quand on s'attaque à la technique XML lol

    voici le xsl final, c'est au poil
    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
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    <?xml version="1.0" encoding="iso-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    	<xsl:key name="positions" match="pos" use="@y"/>
    	<xsl:template match="/">
    		<html>
    			<head>
    			</head>
    			<body>
    				<xsl:for-each select="park">
    					<tr>
    						<td valign="top"><font face="arial"><xsl:value-of select="concat(@id,' ',nom)" /></font></td>
    					</tr>
    					<table border="1">
    						<tr valign="bottom">
    							<td align="right"><font face="arial"></font></td>
    							<!-- PREMIERE BOUCLE: Fixer les numeros (1 à x) en 1ere ligne  -->
    							<xsl:call-template name="ligne1">
    								<xsl:with-param name="compteur" select="1" />
    								<xsl:with-param name="finboucle" select="x" />
    							</xsl:call-template>
    						</tr>
    						<!-- DEUXIEME BOUCLE: pour i=1 a Nombre de ligne (y) -->
    						<xsl:call-template name="lignes">
    							<xsl:with-param name="compteur" select="y" />
    							<xsl:with-param name="finboucle" select="1" />
    						</xsl:call-template>
    					</table>
    				</xsl:for-each>
    			</body>
    		</html>
    	</xsl:template>
     
    <!-- Première ligne, Numérotation -->	
    	<xsl:template name="ligne1">
    	 <xsl:param name="compteur" />
    	 <xsl:param name="finboucle" />
    	 <xsl:choose>
    	  <xsl:when test="$compteur &lt;= $finboucle">
    		<td align="right"><font face="arial"><xsl:value-of select="$compteur" /></font></td>
    		<xsl:call-template name="ligne1">
    			<xsl:with-param name="compteur" select="$compteur + 1" />
    			<xsl:with-param name="finboucle" select="$finboucle" />
    		</xsl:call-template>
    	  </xsl:when>
    	  <xsl:otherwise>
    	  </xsl:otherwise>
    	 </xsl:choose>
    	</xsl:template>
     
    <!-- Boucle sur le nombre de lignes -->	
    	<xsl:template name="lignes">
    	 <xsl:param name="compteur" />
    	 <xsl:param name="finboucle" />
    	 <xsl:choose>
    	  <xsl:when test="$compteur &gt;= $finboucle">
    		<tr valign="bottom">
    			<!-- Numerotation de la ligne -->
    			<td align="right"><font face="arial"><xsl:value-of select="$compteur" /></font></td>
    			<!-- Génération de la ligne courante -->
    			<xsl:call-template name="affiche-cellule">
    				<xsl:with-param name="num-ligne" select="$compteur" />
    				<xsl:with-param name="num-colonne" select="1" />
    				<xsl:with-param name="nombre-colonnes" select="x" />
    			</xsl:call-template>
    		</tr>
    		<xsl:call-template name="lignes">
    			<xsl:with-param name="compteur" select="$compteur - 1" />
    			<xsl:with-param name="finboucle" select="$finboucle" />
    		</xsl:call-template>
    	  </xsl:when>
    	  <xsl:otherwise>
    	  </xsl:otherwise>
    	 </xsl:choose>
    	</xsl:template>
     
    <!-- Generation des cellules d'une ligne -->
    	<xsl:template name="affiche-cellule">
    	  <xsl:param name="num-ligne"/>
    	  <xsl:param name="num-colonne" select="1"/>
    	  <xsl:param name="nombre-colonnes"/>
    	  <xsl:if test="$num-colonne &lt;= $nombre-colonnes">
    		<xsl:variable name="cellule" select="key('positions', $num-ligne)[@x = $num-colonne]"/>
    		<td>
    			<xsl:choose>
    				<xsl:when test="$cellule">
    					<xsl:choose>
    						<xsl:when test="$cellule/@bloque = 'O'">
    							<!-- PLACE INOCCUPABLE -->
    							<xsl:attribute name="align">center</xsl:attribute>
    							<font face="arial" color="#000000">X</font>
    						</xsl:when>
    						<xsl:otherwise>
    							<!-- PLACE OCCUPEE -->
    							<xsl:variable name="Infos">Id:<xsl:value-of select="$cellule/vehicule/@id" /> (<xsl:value-of select="$cellule/vehicule/marque" /> - <xsl:value-of select="$cellule/vehicule/type" /> - <xsl:value-of select="$cellule/vehicule/chevaux" /> - <xsl:value-of select="$cellule/@x" />/<xsl:value-of select="$cellule/@y" />)</xsl:variable>
    							<xsl:variable name="Lien">window.open('../infopark.php?id=<xsl:value-of select="$cellule/vehicule/@id"/>','vehicule_Stat','height=350, width=390, scrollbars=1, status=0, toolbar=0, menubar=0');</xsl:variable>
    								<xsl:attribute name="align">center</xsl:attribute>
    								<xsl:attribute name="title"><xsl:value-of select="$Infos" /></xsl:attribute>
    								<xsl:attribute name="onclick"><xsl:value-of select="$Lien"/></xsl:attribute>
    								<font face="arial" color="#FF0000">O</font>
    						</xsl:otherwise>
    					</xsl:choose>
    				</xsl:when>
    				<xsl:otherwise>
    					<!-- Cellule vide -->
    					<xsl:attribute name="align">center</xsl:attribute>
    					<font face="arial"> </font>
    				</xsl:otherwise>
    			</xsl:choose>
    		</td>
    		<xsl:call-template name="affiche-cellule">
    		  <xsl:with-param name="num-ligne" select="$num-ligne"/>
    		  <xsl:with-param name="num-colonne" select="$num-colonne + 1"/>
    		  <xsl:with-param name="nombre-colonnes" select="$nombre-colonnes"/>
    		</xsl:call-template>
    	  </xsl:if>
    	</xsl:template>
     
    </xsl:stylesheet>

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

Discussions similaires

  1. Extraire les données d'un tableau html dans un xml
    Par nathamis dans le forum Langage
    Réponses: 1
    Dernier message: 25/02/2014, 13h27
  2. Génération d'une page HTML à partir de XML et XSL
    Par clubist dans le forum Servlets/JSP
    Réponses: 10
    Dernier message: 06/12/2010, 11h21
  3. [PHP 4] Extraire des données d'un fichier xml via xsl et xpath
    Par fraisa1985 dans le forum Langage
    Réponses: 1
    Dernier message: 12/01/2010, 10h23
  4. [FF][XSLT][JS] Affichage xml via xsl sous Mozilla
    Par Eileen dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 26/04/2007, 12h13
  5. faire passer des balise html d'un XML vers un XLS
    Par shaftJackson dans le forum XML/XSL et SOAP
    Réponses: 5
    Dernier message: 26/04/2006, 16h07

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