Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1929 connectés 

  FORUM HardWare.fr
  Programmation
  PHP

  XSLT / XML : position d'un noeud

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

XSLT / XML : position d'un noeud

n°2144174
Ellia
Peace and Love
Posté le 31-05-2012 à 16:02:27  profilanswer
 

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
 

mood
Publicité
Posté le 31-05-2012 à 16:02:27  profilanswer
 

n°2144283
gelatine_v​elue
Posté le 01-06-2012 à 13:15:13  profilanswer
 

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

n°2144287
gilou
Modérateur
Modzilla
Posté le 01-06-2012 à 13:25:54  profilanswer
 

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é!  --
n°2144292
Ellia
Peace and Love
Posté le 01-06-2012 à 14:00:41  profilanswer
 

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

n°2144305
gilou
Modérateur
Modzilla
Posté le 01-06-2012 à 15:15:43  profilanswer
 

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é!  --
n°2144514
Ellia
Peace and Love
Posté le 04-06-2012 à 16:04:13  profilanswer
 

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

n°2144515
gelatine_v​elue
Posté le 04-06-2012 à 16:06:51  profilanswer
 

Ellia a écrit :

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


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

n°2144517
gilou
Modérateur
Modzilla
Posté le 04-06-2012 à 16:37:17  profilanswer
 

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é!  --
n°2144524
Ellia
Peace and Love
Posté le 04-06-2012 à 17:03:47  profilanswer
 

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
n°2144541
gilou
Modérateur
Modzilla
Posté le 04-06-2012 à 19:44:11  profilanswer
 

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é!  --
mood
Publicité
Posté le 04-06-2012 à 19:44:11  profilanswer
 

n°2144655
Ellia
Peace and Love
Posté le 05-06-2012 à 16:36:26  profilanswer
 

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!

n°2144664
gelatine_v​elue
Posté le 05-06-2012 à 17:41:20  profilanswer
 

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>  

n°2144677
gilou
Modérateur
Modzilla
Posté le 05-06-2012 à 20:24:35  profilanswer
 

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é!  --
n°2145107
Ellia
Peace and Love
Posté le 08-06-2012 à 10:48:40  profilanswer
 

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é .?

n°2145122
gilou
Modérateur
Modzilla
Posté le 08-06-2012 à 11:40:22  profilanswer
 

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é!  --
n°2147585
Ellia
Peace and Love
Posté le 29-06-2012 à 14:48:16  profilanswer
 

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?

n°2147588
gilou
Modérateur
Modzilla
Posté le 29-06-2012 à 15:15:24  profilanswer
 

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é!  --
n°2147589
Ellia
Peace and Love
Posté le 29-06-2012 à 15:45:30  profilanswer
 

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

n°2147591
gilou
Modérateur
Modzilla
Posté le 29-06-2012 à 15:49:27  profilanswer
 

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é!  --
n°2147592
Ellia
Peace and Love
Posté le 29-06-2012 à 16:03:50  profilanswer
 

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.         ) ;

n°2147595
gilou
Modérateur
Modzilla
Posté le 29-06-2012 à 16:27:57  profilanswer
 

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é!  --
n°2147596
Ellia
Peace and Love
Posté le 29-06-2012 à 16:43:26  profilanswer
 

ç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...
 
:(((

n°2147601
gelatine_v​elue
Posté le 29-06-2012 à 17:08:44  profilanswer
 

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!
 

n°2147603
gilou
Modérateur
Modzilla
Posté le 29-06-2012 à 17:29:10  profilanswer
 

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é!  --
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  PHP

  XSLT / XML : position d'un noeud

 

Sujets relatifs
Parser du XML : récup d'un attributnombre d'occurrences dans un XML avec PHP
XML Copy EditorEditeur XML gratuit permettant d'intégrer le DTD
Modifier le fichier xml avec un feuille XSLTUtiliser le contenu d'un fichier XML
[C# / LINQ to XML] Générer des balises contenant des ':'[XML] Remises informatisées d'ordres de paiement SEPA (ISO 20022)
Requête SQL - Position dans un classementProbleme de position de DIV une ptite aide svp
Plus de sujets relatifs à : XSLT / XML : position d'un noeud


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR