XSL : Select distinct values (xPATH 1.0)

28-01-2014
Laurent Bientz

Imaginons un flux XML composé d'une collection d'une même famille (staff par exemple), que chaque noeud staff possède N skills et que vous souhaitez connaitre en XSL les valeurs distinctes de l'ensemble des skills.

<?xml version="1.0" encoding="UTF-8"?>
<root>
||t||<View>
||t||||t||<wandiz>
||t||||t||||t||<staff>
||t||||t||||t||||t||<id>1</id>
||t||||t||||t||||t||<name>Laurent Bientz</name>
||t||||t||||t||||t||<skills>
||t||||t||||t||||t||||t||<skill>PHP5</skill>
||t||||t||||t||||t||||t||<skill>MySQL5</skill>
||t||||t||||t||||t||||t||<skill>XML</skill>
||t||||t||||t||||t||||t||<skill>XSL</skill>
||t||||t||||t||||t||||t||<skill>xPATH</skill>
||t||||t||||t||||t||</skills>
||t||||t||||t||</staff>
||t||||t||||t||<staff>
||t||||t||||t||||t||<id>2</id>
||t||||t||||t||||t||<name>Florian Collot</name>
||t||||t||||t||||t||<skills>
||t||||t||||t||||t||||t||<skill>PHP5</skill>
||t||||t||||t||||t||||t||<skill>Admin sys</skill>
||t||||t||||t||||t||</skills>
||t||||t||||t||</staff>
||t||||t||||t||<staff>
||t||||t||||t||||t||<id>3</id>
||t||||t||||t||||t||<name>Kevin Lancien</name>
||t||||t||||t||||t||<skills>
||t||||t||||t||||t||||t||<skill>HTML5</skill>
||t||||t||||t||||t||||t||<skill>CSS3</skill>
||t||||t||||t||||t||||t||<skill>Mootools</skill>
||t||||t||||t||||t||</skills>
||t||||t||||t||</staff>
||t||||t||||t||<staff>
||t||||t||||t||||t||<id>5</id>
||t||||t||||t||||t||<name>Jacques De Lamballerie</name>
||t||||t||||t||||t||<skills>
||t||||t||||t||||t||||t||<skill>PHP5</skill>
||t||||t||||t||||t||||t||<skill>MySQL5</skill>
||t||||t||||t||||t||||t||<skill>jQuery</skill>
||t||||t||||t||||t||</skills>
||t||||t||||t||</staff>
||t||||t||||t||<!-- ... -->
||t||||t||</wandiz>
||t||</View>
</root>

En xPATH 2.0, il suffirait d'utiliser la fonction distinct-values():

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:template name="showSkills">
||t||||t||<ul>
||t||||t||||t||<xsl:for-each select="distinct-values(//skill)">
||t||||t||||t||||t||<li><xsl:value-of select="." /></li>
||t||||t||||t||</xsl:for-each>
||t||||t||</ul>
||t||</xsl:template>
</xsl:stylesheet>

En xPATH 1.0, la tache est un peu plus ardue, il faut se baser sur le sibling:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:template name="showSkills">
||t||||t||<ul>
||t||||t||||t||<xsl:for-each select="//skill[not(preceding::skill/. = .)]">
||t||||t||||t||||t||<li><xsl:value-of select="." /></li>
||t||||t||||t||</xsl:for-each>
||t||||t||</ul>
||t||</xsl:template>
</xsl:stylesheet>

 

Angie Menegay - 2015-05-18 19:56:04
Thanks for the example!
Marty - 2016-05-17 06:15:59
Did you mean to have :
version="1.0"
in your first example?
Chetan Naik - 2018-02-06 12:26:05
Thanks a lot. It worked With xPATH 1.0.
Thibaut - 2018-12-07 00:21:52
Merci beaucoup Laurent, j'ai bien galéré avant de trouver ta solution :)

Expérience utilisateur

Wandi vous propose de découvrir une nouvelle approche de la navigation sur un site web...
Êtes-vous prêt ?

Démarrer l'expérience