Home. 
.

transparent

transparent

transparent

Altova Mailing List Archives


Re: Tip: Finding & counting unique nodes in XSL

From: Victor <engmark-usenet@------.----.-->
To: NULL
Date: 6/1/2004 8:50:00 AM
Piet Blok wrote:

> However, I just cannot get rid of an ugly xsl:if. In my solution I 
> select all elements and then I decide if the current element is a "new" 
> element. See below:
> 
> 
> <xsl:template match="/">
> <!-- select all Name elements -->
>     	<xsl:for-each select="//Name">
> <!-- test if this Name element is new, based on the first character -->
>     	    	<xsl:if test="not(substring(current(),1,1) = substring
> (preceding::Name[substring(.,1,1)=substring(current(),1,1)],1,1))">
> <!-- Display the first character -->
>     	    	    	<xsl:value-of select="substring(.,1,1)"/>
> <!-- Count occurences of element with the same starting character -->
>     	    	    	<xsl:value-of select="count(//Name[substring(.,1,1)
> =substring(current(),1,1)])"/>
>     	    	</xsl:if>
>     	</xsl:for-each>
> </xsl:template>
> 
> Can you think of any way to move the if structure into the select 
> clause?
> 
> In a way the problem seems to be that there are three contexts to deal 
> with: the context node (in this case the root node), the node that is 
> currently under investigation for selection and the node that is 
> compared to (between the square brackets).

First, if you can split the Name into several strings, that would be a 
good start. If you have control over the structure of the XML file, keep 
each piece of information separate. Otherwise you'll get into the same 
mess I was in when trying to make sense of MS Project XML files (gross!).

Then there is a funny thing about the test (changed the substring 
function to a() to make it obvious):
a(current) = a(preceding::Name[a(.)=a(current)])
So first you find a preceding Name which equals the current one, and 
then compare it to the current one? This sounds like double work. 
a(current) = a(preceding::Name) should be enough.

By changing according to the previous paragraphs, you would have 
something like a Name element and a New element, and you can do the 
for-each as follows (providing that the New element occurs after the Name):
<xsl:for-each select="//Name[not(./following-sibling::New = 
preceding::Name/following-sibling::New)]">

I haven't tested this, but perhaps someone with more XSL experience can 
point out any obvious errors.

-- 
Victor


transparent
Print
Mail
Like It
Disclaimer
.

These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on www.altova.com/list/index.html. Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.

.
.

transparent

transparent