XSLT / XML : position d'un noeud

XSLT / XML : position d'un noeud - PHP - Programmation

Marsh Posté le 31-05-2012 à 16:02:27    

Bonjour à tous,
 
fisrt time que je poste un message sur un forum, c'est vraiment que j'en ai besoin !  
 
Alors, j'ai un fichier XML qui comprend plusieurs champ : En voici un bout de la structure :  
 
<champ id="Table1" genre="numerique">
           <eti num="1">
        <titre lang="fr">Oui</titre>
           </eti>
 </champ>
 <champ id="table2" genre="numerique">
         <eti num="1">
        <titre lang="fr">Oui</titre>
      </eti>
 </champ>
 
 
 
et donc, dans mon fichier XSL, je veux afficher mes noms de champs accompagnés du "num" de l'étiquette. Je fais donc une concaténation qui fonctionne sans soucis.
 
Pour traiter ces champs spéciaux ( ceux qui possèdent "une étiquette" ), je les mets dans une boucle :  
  <xsl:template match="champ[@genre='numerique']/eti">
       `<xsl:value-of select="concat(../@id,'__',@num)"/>` VALEUR       <xsl:call-template name="Recursif"/>
    </xsl:template>  
 
AINSI, vient mon soucis. Je veux qu'à la derniere boucle sur les champs ( TOUS LES CHAMPS ), on me mette un espace blanc, et que si c'est pas le dernier, on me mette une virgule :  
 
  <xsl:template name="Recursif">
        <xsl:if test = "not(position()=last())">,
        </xsl:if><xsl:if test = "position()=last()">  </xsl:if>  
    </xsl:template>
 
 
CEPENDANT, lorsque, je boucle sur ((((   <xsl:template match="champ[@genre='numerique']/eti"> )))), et ben il me met tout le temps la virgule, même si c'est le dernier champ !!!!  
 
si quelqu'un aurait une idée ! ça ne sera pas de refus ! S'il vous plait, bien sur ;)
 
Ellia
 

Reply

Marsh Posté le 31-05-2012 à 16:02:27   

Reply

Marsh Posté le 01-06-2012 à 13:15:13    

Moi j'ai une idée: utilise un for-each.

Reply

Marsh Posté le 01-06-2012 à 13:25:54    

Citation :

si quelqu'un aurait une idée ! ça ne sera pas de refus ! S'il vous plait, bien sur

Ben imprime déjà les valeurs de position et last dans ton template pour savoir ce qui se passe.
Et mets plutôt test="position()!=last()" dans ton test
Et plutôt que deux xsl:if, utilise un choose when otherwise
 
<xsl:template name="Recursif">  
  <xsl:choose>
     <xsl:when test="position()!=last()" >,  
        </xsl:when>
     <xsl:otherwise> </xsl:otherwise>
  </xsl:choose>
</xsl:template>
 
A+,


Message édité par gilou le 01-06-2012 à 13:36:45

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 01-06-2012 à 14:00:41    

Merci gilou. cependant, ça ne change rien, il ne voit tout de même pas la fin, lorque je suis dans une "eti" . donc j'ai toutjours une virgule, même quand c'est la fin

Reply

Marsh Posté le 01-06-2012 à 15:15:43    

Heureusement que j'avais mis ça, hein...

Citation :

Ben imprime déjà les valeurs de position et last dans ton template pour savoir ce qui se passe.


 
Si ça ne marche pas, c'est surement que le node-set que vous passez au template est pas le bon.
Explication:
Quand vous faites  
 
<xsl:template match="champ[@genre='numerique']/eti">  
     `<xsl:value-of select="concat(../@id,'__',@num)"/>` VALEUR  <xsl:call-template name="Recursif"/>
</xsl:template>  
votre match va sélectionner un seul eti a la fois pour le passer au template Recursif, alors que ce que vous voulez faire, c'est récupérer la liste des eti dans un noeud champ et avoir une sortie variable selon leur position dans la liste. Pour collecter des noeuds et en faire une liste, on utilise un xsl:for-each avec un select qui convient:
 
<xsl:template match="champ[@genre='numerique']">  
  <xsl:for-each select="eti">
     `<xsl:value-of select="concat(../@id,'__',@num)"/>` VALEUR  <xsl:call-template name="Recursif"/>
  </xsl:for-each>  
</xsl:template>
 
Ceci devrait maintenant avoir comme node set la liste des eti dans un champ, de ce fait, les valeurs last et position vont être par rapport à ce node set et ça va coller.
 
A+,


Message édité par gilou le 01-06-2012 à 16:24:58

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 04-06-2012 à 16:04:13    

Merci beaucoup Gilou ! ça marche nikel !!!!

Reply

Marsh Posté le 04-06-2012 à 16:06:51    

Ellia a écrit :

Merci beaucoup Gilou ! ça marche nikel !!!!


 
Lol, ce que j'avais mis dans le second post quoi...

Reply

Marsh Posté le 04-06-2012 à 16:37:17    

T'avais pas été assez pédagogique :p
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 04-06-2012 à 17:03:47    

Ouais mais finalement, ce que je fais ne marche pas.  
 
En effet, il m'enleve bien la virgule au dernier "eti" mais le soucis c'est qu'il me l'enleve tout le temps. Même quand c'est pas  le dernier champ. :(


Message édité par Ellia le 04-06-2012 à 17:03:59
Reply

Marsh Posté le 04-06-2012 à 19:44:11    

Donc ce que tu veux faire n'est pas clair, car j'ai testé sur un exemple:

Code :
  1. <doc>
  2.  <champ id="Table1" genre="numerique">
  3.    <eti num="1">
  4.      <titre lang="fr">Oui</titre>
  5.    </eti>
  6.    <eti num="2">
  7.      <titre lang="en">non</titre>
  8.    </eti>
  9.  </champ>
  10.  <champ id="table2" genre="numerique">
  11.    <eti num="1">
  12.      <titre lang="fr">Oui</titre>
  13.    </eti>
  14.  </champ>
  15. </doc>


avec comme script xsl

Code :
  1. <?xml version="1.0" encoding="ISO-8859-1"?>
  2. <xsl:stylesheet version="1.0"  
  3. xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  4. <xsl:output method="text"/>
  5. <xsl:template match="champ[@genre='numerique']">  
  6.  <xsl:for-each select="eti">
  7.     `<xsl:value-of select="concat(../@id,'__',@num)"/>` VALEUR  <xsl:call-template name="Recursif"/>
  8.  </xsl:for-each>  
  9. </xsl:template>  
  10. <xsl:template name="Recursif">
  11.  <xsl:choose>  
  12.     <xsl:when test="position()!=last()">,  
  13.        </xsl:when>  
  14.     <xsl:otherwise> </xsl:otherwise>  
  15.  </xsl:choose>
  16. </xsl:template>  
  17. </xsl:stylesheet>


et saxon comme processeur xsl

"C:\Program Files\Saxonica\SaxonHE9.4N\bin\Transform.exe" -t -s:champs.xml -xsl:champs.xsl -o:out.xml


et pour moi ça colle en sortie, le premier a bien la virgule attendue:


     `Table1__1` VALEUR  ,  
         
     `Table1__2` VALEUR    
 
     `table2__1` VALEUR    


 
A+,


Message édité par gilou le 04-06-2012 à 21:57:16

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 04-06-2012 à 19:44:11   

Reply

Marsh Posté le 05-06-2012 à 16:36:26    

Voilà, je comprend parfaitement ce que tu viens de faire.
Seulement, il me fait une virgule apres "  `Table1__2` VALEUR  " , car je ne veux pas qu'il y ait de virgule à la DERNIERE eti, du DERNIER champ !  
Et c'est ça que je n'arrive pas à trouver !  
Donc si vous avez une idée monsieur Gillou, ou quelqu'un ? ça serait pas de refus!

Reply

Marsh Posté le 05-06-2012 à 17:41:20    

Ellia a écrit :

Voilà, je comprend parfaitement ce que tu viens de faire.
Seulement, il me fait une virgule apres "  `Table1__2` VALEUR  " , car je ne veux pas qu'il y ait de virgule à la DERNIERE eti, du DERNIER champ !  
Et c'est ça que je n'arrive pas à trouver !  
Donc si vous avez une idée monsieur Gillou, ou quelqu'un ? ça serait pas de refus!


 
Il te suffit de changer le sélecteur de ta boucle for, et de la faire partir de plus haut (code non testé):
 
<xsl:template match="/doc">  
 <xsl:for-each select=".//eti">
    `<xsl:value-of select="concat(../@id,'__',@num)"/>` VALEUR  <xsl:call-template name="Recursif"/>
 </xsl:for-each>  
</xsl:template>  

Reply

Marsh Posté le 05-06-2012 à 20:24:35    

Oui, c'était clair:

<xsl:template match="/doc">  
  <xsl:for-each select="champ[@genre='numerique']eti">


ou

<xsl:template match="/">  
  <xsl:for-each select="*/champ[@genre='numerique']eti">


va clairement coller
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 08-06-2012 à 10:48:40    

Merci à tous pour vos réponses. Cela dit, un soucis persiste.  
Mon code arrive bien à retirer la virgule si c'est la derniere 'ETI' du fichier. Cependant, si il me reste un <champ> après cette 'ETI', il me retire tout de même ma virgule ...  
Aurez vous une solution pour que lorsque si c'st PAS le dernier "CHAMP" et ben tu me met une virgule.
 
J'ai pensais à un "if" imbriqué .?

Reply

Marsh Posté le 08-06-2012 à 11:40:22    

Oui, parce qu'on va pas non plus faire tout ton boulot gratuitement à ta place.
C'est la même technique que celle qu'on vient d'utiliser, en un tout petit peu plus compliqué, il va juste falloir que tu réfléchisse un peu pour comprendre à quel niveau tu démarre ta collecte de noeuds à traiter en une node-list. Ça se fait en 5 mn (c'est le temps que ça m'a pris pour modifier le xsl et tester).
A+,


Message édité par gilou le 08-06-2012 à 12:04:27

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 29-06-2012 à 14:48:16    

Re bonjour !!!
 
Je ré-ouvre le sujet, car un problème persiste !
 
 
     

Code :
  1. <xsl:template match="champ[@genre='numerique]">
  2.       <xsl:for-each select="eti">
  3.           `<xsl:value-of select="concat(../@id,'__',@code)"/>` VARCHAR(80)
  4.      <xsl:choose>
  5.           <xsl:when test="generate-id(../eti) = generate-id((/../champ)[last()])" >  <xsl:if test="generate-id(.) = generate-id((//eti)[last()])">  </xsl:if> <xsl:if test="generate-id(.) != generate-id((//eti)[last()])"> ,  </xsl:if>  
  6.           </xsl:when>
  7.           <!-- Le When teste si on est dans le dernier champ du fichier. Le if teste si on est la dernière etiquette -->
  8.           <xsl:otherwise> , </xsl:otherwise> 
  9.     </xsl:choose>
  10.                 </xsl:for-each>
  11.         </xsl:template>


 
mon fichier XML ( la fin )

Code :
  1. <champ id="f_num">
  2.       <titre lang="fr">choixmult</titre>
  3.       <eti code="1">
  4.         <titre lang="fr">choix1</titre>
  5.       </eti>
  6.       <eti code="2">
  7.         <titre lang="fr">choix2</titre>
  8.         </eti>
  9.     </champ>


 
Cependant, lorsque je suis dans le dernier champ, et à la dernière ETI, il me met encore une virgule..
 
Auriez vous une idée?

Reply

Marsh Posté le 29-06-2012 à 15:15:24    

Il persiste certainement, puisque tu n'emploies pas les techniques que l'on t'a indiqué auparavant, et qui elles marchent parfaitement.
 
On t'avait donné ceci comme solution:

Code :
  1. <?xml version="1.0" encoding="ISO-8859-1"?>
  2. <xsl:stylesheet version="1.0"  
  3. xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  4. <xsl:output method="text"/>
  5. <xsl:template match="/doc">  
  6.  <xsl:for-each select="champ[@genre='numerique']/eti">
  7.     `<xsl:value-of select="concat(../@id,'__',@num)"/>` VALEUR  <xsl:call-template name="Recursif"/>
  8.  </xsl:for-each>  
  9. </xsl:template>  
  10. <xsl:template name="Recursif">
  11.  <xsl:choose>  
  12.     <xsl:when test="position()!=last()" >,  
  13.        </xsl:when>  
  14.     <xsl:otherwise> </xsl:otherwise>  
  15.  </xsl:choose>
  16. </xsl:template>  
  17. </xsl:stylesheet>


 
Si elle ne te convient pas, donne un exemple de fichier test qui ne marche pas, avec la sortie que tu obtiens et celle que tu voudrais obtenir.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 29-06-2012 à 15:45:30    

Non cela ne fontionne pas :(
D'ailleurs il me zappe mes genre numérique ...
 

Reply

Marsh Posté le 29-06-2012 à 15:49:27    

Citation :

Si elle ne te convient pas, donne un exemple de fichier test qui ne marche pas, avec la sortie que tu obtiens et celle que tu voudrais obtenir.


Rhaaa!
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 29-06-2012 à 16:03:50    

Mon xml :  
 
 

Code :
  1. <?xml version="1.0" encoding="ISO-8859-15"?>
  2. <!DOCTYPE formulaire SYSTEM "form.dtd">
  3. <formulaire id="formulaire" titre="1">
  4.   <section id="s_Verification">
  5.     <champ id="condition_" genre="texte" >
  6.       </champ>
  7. <champ id="condition_6" genre="num" required="true">
  8.         <titre lang="fr">Partis en vacances1 /titre>
  9.           <eti code="2">
  10.           <titre lang="fr">Non</titre>
  11.           </eti>
  12.       </champ>
  13.       <champ id="condition_7" genre="num" required="true">
  14.         <titre lang="fr">Partis en vacances /titre>
  15.           <eti code="1">
  16.           <titre lang="fr">Non</titre>
  17.           </eti>
  18.       </champ>
  19.    </section>
  20.   </formulaire>


 
 
Mon code XSLT  
 
     
 
   

Code :
  1. <xsl:template match="champ[@genre='num']">
  2.       <xsl:for-each select="eti">
  3.           `<xsl:value-of select="concat(../@id,'__',@code)"/>` Valeurs
  4.      <xsl:choose>
  5.           <xsl:when test="generate-id(../eti) = generate-id((/../champ)[last()])" ><xsl:if test="generate-id(.) = generate-id((//eti)[last()])"></xsl:if><xsl:if test="generate-id(.) != generate-id((//eti)[last()])"> , </xsl:if>  
  6.           </xsl:when>
  7.           <xsl:otherwise> , </xsl:otherwise> 
  8.     </xsl:choose>
  9.                 </xsl:for-each>
  10.         </xsl:template>


 
En sortie  
 

Code :
  1. Create table (
  2. `condition` text ,
  3.      `condition_6__1` Valeurs,
  4.           `condition_7__1` Valeurs ,
  5.         ) ;


 
 
Ce que je voudrais :  
 
 

Code :
  1. Create table (
  2. `condition` text ,
  3.      `condition_6__1` Valeurs,
  4.        
  5.           `condition_7__1` Valeurs
  6.         ) ;

Reply

Marsh Posté le 29-06-2012 à 16:27:57    

Quand je fais ceci sur ton exemple, juste en adaptant les noms de tags et les paths qui ont changé par rapport a ce que tu avais donné auparavant

Code :
  1. <?xml version="1.0" encoding="ISO-8859-1"?>
  2. <xsl:stylesheet version="1.0"  
  3. xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  4. <xsl:output method="text"/>
  5. <xsl:template match="/">
  6.  Create table (
  7.  <xsl:apply-templates/>
  8.  );
  9. </xsl:template>
  10. <xsl:template match="section">  
  11.  <xsl:for-each select="champ[@genre='num']/eti">
  12.     `<xsl:value-of select="concat(../@id,'__',@code)"/>` VALEUR  <xsl:call-template name="Recursif"/>
  13.  </xsl:for-each>  
  14. </xsl:template>  
  15. <xsl:template name="Recursif">
  16.  <xsl:choose>  
  17.     <xsl:when test="position()!=last()" >,  
  18.        </xsl:when>  
  19.     <xsl:otherwise> </xsl:otherwise>  
  20.  </xsl:choose>
  21. </xsl:template>  
  22. </xsl:stylesheet>


j'obtiens:


  Create table (
   
   
     `condition_6__2` VALEUR  ,  
         
     `condition_7__1` VALEUR  
 
  );


 
J'ai pas traité ton `condition` text , puisque c'est nouveau, ça vient de sortir, et que je ne sais pas ce que tu veux faire avec les champs de genre non num à la base.
 
A+,


Message édité par gilou le 29-06-2012 à 16:28:22

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 29-06-2012 à 16:43:26    

ça ne fonctionne pas du tout chez moi ! C'est pire :(
 
ça ne me met pas de virgules dès que c'est la dernière eti du champ. Mais moi je n'en veux pas que quand on est le dernier CHAMP du fichier...
 
:(((

Reply

Marsh Posté le 29-06-2012 à 17:08:44    

Ellia a écrit :

ça ne fonctionne pas du tout chez moi ! C'est pire :(
 
ça ne me met pas de virgules dès que c'est la dernière eti du champ. Mais moi je n'en veux pas que quand on est le dernier CHAMP du fichier...
 
:(((


 
Attends, mais ce serait pas le meme post que celui du 05-06-2012 à 16:36:26?  [:hide]  
We've gone back in time!
 

Reply

Marsh Posté le 29-06-2012 à 17:29:10    

Ellia a écrit :

ça ne fonctionne pas du tout chez moi ! C'est pire :(
 
ça ne me met pas de virgules dès que c'est la dernière eti du champ. Mais moi je n'en veux pas que quand on est le dernier CHAMP du fichier...
 
:(((

Sur l'exemple que je vous ai donné, ça marche parfaitement avec un processeur xslt standard comme saxon (cf ma sortie en exemple).
le log du processing:

C:\XML>"C:\Program Files\Saxonica\SaxonHE9.4N\bin\Transform.exe" -t -s:champs.xml -xsl:champs.xsl -o:champs.txt
Saxon-HE 9.4.0.2N from Saxonica
.NET 2.0.50727.3634 on Microsoft Windows NT 5.1.2600 Service Pack 3
URIResolver.resolve href="file:/C:/XML/champs.xsl" base="null"
Using parser org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser
Warning: at xsl:stylesheet on line 3 column 50 of champs.xsl:
  Running an XSLT 1 stylesheet with an XSLT 2 processor
Stylesheet compilation time: 1515 milliseconds
Processing file:/C:/XML/champs.xml
Building tree for file:///C:/XML/champs.xml using class net.sf.saxon.tree.tiny.TinyBuilder
Tree built in 31 milliseconds
Tree size: 34 nodes, 54 characters, 17 attributes
Execution time: 250ms
Memory used: 3089140
NamePool contents: 13 entries in 13 chains. 6 URIs


Si vous utilisez des outils défectueux ou non conformes, je ne peux rien pour vous.
 [:souk]  
Vous pouvez vérifier sous windows par exemple avec le parser xsl gratuit de microsoft que l'on trouve ici: http://download.cnet.com/Command-L [...] 31054.html
 

C:\XML>msxsl champs.xml champs.xsl -o champs.txt -t
Microsoft (R) XSLT Processor Version 3.0
 
Source document load time:     0 milliseconds
Stylesheet document load time: 0 milliseconds
Stylesheet compile time:       0 milliseconds
Stylesheet execution time:     0 milliseconds


Et ça donne exactement le même résultat qu'avec Saxon:


  Create table (
   
   
     `condition_6__2` VALEUR  ,  
         
     `condition_7__1` VALEUR  
 
  );


Note: mon document xml de test était celui que vous avez fourni, moins la ligne définissant la DTD du document, car je n'y ai pas accès.
A+,


Message édité par gilou le 29-06-2012 à 20:25:32

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed