Reputation:
I have xml like
<categories>
<category>
<LOC>USA,UK,Spain <LOC>
</category>
<category>
<LOC>India,USA,China <LOC>
</category>
<categories>
I don't want to get the USA two times when I am displaying LOC
<xsl:value of select="$LOC/>
I was thinking of using some variable
<xsl:variable name="ABC" select="set:distinct(//LOC)"/>
<xsl:value-of select="$ABC"/>
But its not working Any idea what could be the problem
EDIT: sorry I edited my xml I typed it in wrong
Upvotes: 0
Views: 2307
Reputation: 60448
The EXSLT function set:distinct
operates on node sets. The strings you're passing to it are not node sets, and so this function isn't working. Or rather, it's working perfectly but you're expecting the unreasonable from it.
First of all, you should not be storing comma-separated lists in XML if you can help it. XML is already a delimited format so you should have absolutely no reason to store a delimited format inside of it.
If you have control over the format, you should be using something like this instead:
<categories>
<category>
<LOC>USA</LOC>
<LOC>UK</LOC>
<LOC>Spain</LOC>
</category>
<category>
<LOC>India</LOC>
<LOC>USA</LOC>
<LOC>China</LOC>
</category>
</categories>
If this were you input format, set:distinct
would work just fine the way you're trying to use it.
If you don't have this control over the input format, you're going to find that XSLT really sucks at string manipulation and tokenization (XSLT 2 is more helpful if you have access to it, as Jim Garrison mentioned in a comment). Your best bet is to read the XML into some other structure and tokenize the LOC
element's contents and work with the results directly than trying to do it in XSLT.
Upvotes: 3
Reputation: 86774
Given this XML
<?xml version="1.0" encoding="UTF-8"?>
<categories>
<category>
<LOC>USA,UK,Spain </LOC>
</category>
<category>
<LOC>India,USA,China </LOC>
</category>
</categories>
Here's an XSLT2 stylesheet that will do what you want
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:variable name="LOC">
<xsl:for-each select="//LOC/text()">
<xsl:for-each select="tokenize(current(),',')">
<temp><xsl:value-of select="current()"/></temp>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/">
<xsl:value-of select="distinct-values($LOC/*)"/>
</xsl:template>
</xsl:stylesheet>
It first builds a temporary tree (document fragment) containing one element for each token, then uses distinct-values() to remove duplicates. I coded and tested this in Oxygen/XML.
Upvotes: 3