Retourner aux forums || Retourner au forum Programmation.autre

Programmation.autre : Grouper le traitement de balises via XSLT

Posté par Bonnefille Guilhem (page perso, ) le 09 octobre 2006
0
Bonjour,

Je débute un peu en XSLT et je me trouve confronté à un problème que j'ai un peu de mal à formaliser. Un bon exemple valant mieux qu'un long discours...

Voici un fragment XML :

[resource id="r1" name="Titi" /]
[resource id="r2" name="Titi" /]
[task id="t1" resource="r1" /]
[task id="t2" resource="r1" /]
[task id="t3" resource="r2" /]


Je voudrais traiter chaque task en les regroupant par resource.
Soit, je voudrais obtenir un résultat proche de :

[ul]
[li]Ressource Toto :[/li]
[ul]
[li]r1[/li]
[li]r2[/li]
[/ul]
[/ul]
[ul]
[li]Ressource Titi :[/li]
[ul]
[li]r3[/li]
[/ul]
[/ul]


Dans ma première implémentation, j'étais parti pour n'avoir qu'un seul template, correspondant à "task". Dans ce template, si c'est le premier à traiter de la ressource citée j'ajoute l'introduction (ouvrant entre autre le bloc "ul") et si c'est le dernier je ferme le "ul".
Or, le processeur XSLT râle car mes ouvertures et fermeture du "ul" englobant se font à l'intérieur de "xsl:if" rompant la correspondance entre balises ouvrantes et fermantes.

Quelles solutions utilise-t-on classiquement dans ce genre de cas ?
PS : je souhaiterai éviter de modifier le XML.

> Lire le message (4 commentaires, moyenne: 0,5).  

Cette discussion est archivée, il n'est plus possible de laisser des commentaires.

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.

utiliser <xsl:for-each>

Posté par Nicolas P. (page perso, ) le 09/10/2006 à 10:00. (lien). Évalué à 0.

Pour ce genre de chose le plus simple est d'utiliser le tag <xsl:for-each>. Dans un template associé à l'élément père des éléments <task>, on peut écrire quelque chose de ce genre:

<ul>
<xsl:for-each select="task">
<li><xsl:value-of select="."/></li>
</xsl:for-each>
</ul>

--
this != '|' ;
  • [^]Re: utiliser <xsl:for-each>

    Posté par Bonnefille Guilhem (page perso, ) le 09/10/2006 à 10:08. (lien). Évalué à 1.

    En fait, le problème n'est pas le traitement des task, mais plutôt le fait de faire une seule action pour deux tasks.

    En effet, je n'affiche qu'une seule fois la ressource r1 pour les deux tasks t1 et t2.

    Désolé de ne pas avoir été plus précis dès mon premier post.

    • [^]Re: utiliser <xsl:for-each>

      Posté par Nicolas P. (page perso, ) le 09/10/2006 à 10:30. (lien). Évalué à 0.

      Désolé également, j'ai lu un peu vite. Si je comprends bien, le code dont tu as besoin serait plutôt, toujours dans un template associé au père des éléments <task> et <resource>

      <ul>
      <xsl:for-each select="resource">
      <li>Resource <xsl:value-of select="."/></li>
      <ul>
      <xsl:variable name="resourceId" select="@id"/>
      <xsl:for-each select="../task[@resource=$resourceId]">
      <li>Task <xsl:value-of select="."/></li>
      </xsl:for-each>
      </ul>
      </xsl:for-each>
      </ul>

      --
      this != '|' ;

Ma solution

Posté par Bonnefille Guilhem (page perso, ) le 09/10/2006 à 12:18. (lien). Évalué à 1.

J'ai fini par trouver une solution que je crois relativement élégante.

Dans mon exemple, j'avais oublié que les "task" sont dans un "tasks".
Du coup, sur "tasks" je parcours tous les "resource" de façon uunique avec un "for-each" et un select comme suit :
task[position() = 1 or not(preceding-sibling::node()/@resource = @resource)]

Voilou, ça marche. Et je n'ai qu'un seul "for-each", ce qui est plus dans l'esprit je pense.

Merci à tous.

Revenir en haut de page || Retourner aux forums || Retourner au forum Programmation.autre