tags:

views:

132

answers:

3

I have XML like this:

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

I want it to output like

laptop
charger
headphones

I was trying to use distinct-values() but I guess i m doing something wrong. Can anyone tell me how to achieve this using distinct-values()? Thanks.

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

but its giving me output like this:

<li>laptop</li>
<li>charger</li>
<li>laptop></li>
<li>headphones</li>
+1  A: 

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

Jim Garrison
As long as it is avoidable (when the XML structure is fixed and known), the `//` shorthand should be avoided due to its exponential time complexity (i.e. it's *slow*): `distinct-values(/items/item/product/text())`
Tomalak
A: 

You don't want "output (distinct-values)", but rather "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>
Tomalak
Its working fine...there was some bug in my xml....thanks a lot...
AB
Tomalak xslt 2.0 is not supported by browser...just came to knw...while testing ...any way to do it without xslt 2.0
AB
@Tomalak the XPATH would either be `/items/item/products/product/text()` or `/items/item//product/text()`
Mads Hansen
@AB - I've added an XSLT 1.0 solution
Mads Hansen
@Mads: You are right. Fixed.
Tomalak
+2  A: 

An XSLT 1.0 solution that uses key and the generate-id() function to get distinct values:

<?xml version="1.0" encoding="UTF-8"?>
  <xsl:stylesheet
   version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  <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>
Mads Hansen
Thats work perfectly...........Thanks a lot ....
AB