Comment utiliser XSLT pour créer des valeurs distinctes

J'ai XML comme ceci:

<items>
  <item>
    <products>
      <product>laptop</product>
      <product>charger</product>
    </products>
  </item>
  <item>
    <products>
      <product>laptop</product>
      <product>headphones</product>  
    </products>  
  </item>
</items>

Je veux qu'il sorte comme

laptop
charger
headphones

J'essayais d'utiliser distinct-values() mais je suppose que je fais quelque chose de mal. Quelqu'un peut-il me dire comment y parvenir en utilisant distinct-values()? Grâce.

<xsl:template match="/">            
  <xsl:for-each select="//products/product/text()">
    <li>
      <xsl:value-of select="distinct-values(.)"/>
    </li>               
  </xsl:for-each>
</xsl:template>

Mais cela me donne une sortie comme ceci:

<li>laptop</li>
<li>charger</li>
<li>laptop></li>
<li>headphones</li>
47
demandé sur Erik Philips 2010-02-18 22:27:33

5 réponses

Une solutionXSLT 1.0 qui utilise key et la fonction generate-id() pour obtenir des valeurs distinctes:

<?xml version="1.0" encoding="UTF-8"?>
  <xsl:stylesheet
   version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

<xsl:key name="product" match="/items/item/products/product/text()" use="." />

<xsl:template match="/">

  <xsl:for-each select="/items/item/products/product/text()[generate-id()
                                       = generate-id(key('product',.)[1])]">
    <li>
      <xsl:value-of select="."/>
    </li>
  </xsl:for-each>

</xsl:template>

</xsl:stylesheet>
48
répondu Mads Hansen 2013-04-30 00:06:14

Voici une solution XSLT 1.0 que j'ai utilisée dans le passé, je pense qu'elle est plus succincte (et lisible) que d'utiliser la fonction generate-id().

  <xsl:template match="/">           
    <ul> 
      <xsl:for-each select="//products/product[not(.=preceding::*)]">
        <li>
          <xsl:value-of select="."/>
        </li>   
      </xsl:for-each>            
    </ul>
  </xsl:template>

Renvoie:

<ul xmlns="http://www.w3.org/1999/xhtml">
  <li>laptop</li>
  <li>charger</li>
  <li>headphones</li>
</ul>
45
répondu Nick Grealy 2013-09-19 04:34:10

Vous ne voulez pas de sortie "(distinct-values)", mais plutôt "for-each (distinct-values)":

<xsl:template match="/">              
  <xsl:for-each select="distinct-values(/items/item/products/product/text())">
    <li>
      <xsl:value-of select="."/>
    </li>
  </xsl:for-each>
</xsl:template>
16
répondu Tomalak 2010-02-19 08:25:51

Je suis arrivé à ce problème en travaillant avec un rendu Sitecore XSL. L'approche qui utilisait key () et l'approche qui utilisait l'axe précédent fonctionnaient très lentement. J'ai fini par utiliser une méthode similaire à key () mais qui ne nécessitait pas d'utiliser key(). Il fonctionne très rapidement.

<xsl:variable name="prods" select="items/item/products/product" />
<xsl:for-each select="$prods">
  <xsl:if test="generate-id() = generate-id($prods[. = current()][1])">
    <xsl:value-of select="." />
    <br />
  </xsl:if>
</xsl:for-each>
13
répondu Felix Steiny 2014-04-02 16:00:13

distinct-values(//product/text())

7
répondu Jim Garrison 2012-06-14 21:09:50