Comment puis-je générer une liste séparée par des virgules avec XSLT/XPath?
Compte tenu de ces données XML:
<root> <item>d'apple</item> <item>orange</item> <item>banane</item> </root>
Je peux utiliser cette XSLT balisage:
... <xsl:for-each select="root/item"> <xsl:value-of select="."/>, </xsl:for-each> ...
pour obtenir ce résultat:
pomme, orange, banane,
mais comment puis-je produire une liste où la dernière virgule n'est pas présent? Je suppose qu'il peut être fait de faire quelque chose le long des lignes de:
... <xsl:for-each select="root/item"> <xsl:value-of select="."/> <xsl:if test="...">,</xsl:si> </xsl:for-each> ...
mais ce qui devrait le test d'expression?
J'ai besoin de quelques façon de déterminer combien de temps la liste est et où je suis actuellement dans la liste, ou, à défaut, si je suis en train de traiter le dernier élément dans la liste (ce qui signifie que je ne se soucient pas combien de temps il est ou de ce que la position actuelle est).
Vous devez vous connecter pour publier un commentaire.
Prendre un coup d'oeil à la
position()
,count()
etlast()
fonctions; par exemple,test="position() < last()"
.<xsl:value-of select="@Courses"/>
qui affiche tous les CSV, mais il n'a pas l'air trop convivial. Est-il possible de la place de la virgule, séparez-les par une nouvelle ligne pour chaque valeur?C'est un joli modèle commun:
if not empty
🙂Pour une transformation XSLT 2.0 option, vous pouvez utiliser le
separator
attribut surxsl:value-of
.Ce
xsl:value-of
:d'obtenir ce résultat:
Vous pouvez également utiliser plus que juste une virgule comme séparateur. Par exemple, ceci:
Serait de produire le résultat suivant:
Un autre XSLT 2.0 option est
string-join()
...ou (peut-être plus efficace, mais vous auriez à tester):
Un simple XPath 1.0 one-liner:
concat(., substring(',', 2 - (position() != last())))
Mettre dans cette transformation:
et de l'appliquer au document XML:
pour obtenir le résultat voulu:
apple,orange,banana
EDIT:
Voici un commentaire de Robert Rossney à cette réponse:
et voici ma réponse:
Les gars, n'ayant pas peur d'apprendre quelque chose de nouveau. En fait, c'est tout Débordement de la Pile est d'environ, n'est-ce pas? 🙂
Robert a donné la classis
not(position() = last())
réponse. Cela vous oblige à traiter l'intégralité du nœud actuel de la liste pour obtenir la taille du contexte, et en grande documents d'entrée de ce qui pourrait faire la conversion consomment plus de mémoire. Donc, j'ai l'habitude d'inverser le test pour être la première choseposition()=last()
test utiliser une seule étape d'anticipation, mais la solution de mettre un séparateur avant chaque élément, à l'exception de la première est certainement préférable, parce que (a) il ne comporte aucune anticipation à tous, et (b) il évite toute confiance sur les smart optimisation.C'est la façon dont je l'ai eu à travailler pour moi.
J'ai testé ce à l'encontre de votre liste: