Altova Mailing List Archives>Archive Index >comp.text.xml Archive Home >Recent entries >Thread Prev - Re: Tip: Finding & counting unique nodes in XSL >Thread Next - Re: Tip: Finding & counting unique nodes in XSL Re: Tip: Finding & counting unique nodes in XSLTo: 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 | ||||||
| Company | Legal | Press | Partners | Careers | Sitemap | Contact Us | Altova Blog | Mobile | Full Site | |||
|
