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.
# utiliser <xsl:for-each>
Posté par Nicolas P. . Évalué à 0.
<ul>
<xsl:for-each select="task">
<li><xsl:value-of select="."/></li>
</xsl:for-each>
</ul>
[^] # Re: utiliser <xsl:for-each>
Posté par Bonnefille Guilhem (site web personnel) . Évalué à 1.
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. . Évalué à 0.
<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>
# Ma solution
Posté par Bonnefille Guilhem (site web personnel) . Évalué à 1.
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.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.