Subject: Re: [xsl] CSV data in attribute - how to get unique values? From: Brandon Ibach <brandon.ibach@xxxxxxxxxxxxxxxxxxx> Date: Wed, 5 Jan 2011 04:23:42 -0500 |
Here's a working solution. It isn't the prettiest, but given the minimal string processing features in XSLT 1.0, I don't know that there's a significantly cleaner way to do what you want. <xsl:template match="/"> <!-- List all named bottomlevel items grouped by tokens - - in the "attrib" attribute closest to each item --> <xsl:call-template name="items-by-token"> <xsl:with-param name="items" select="//bottomlevel[@name]"/> </xsl:call-template> </xsl:template> <xsl:template name="items-by-token"> <xsl:param name="items" select="/.."/><!-- Items to list --> <xsl:param name="tokens" select="''"/><!-- Tokens from current item --> <xsl:param name="seen" select="' '"/><!-- Tokens already seen / listed --> <xsl:choose> <xsl:when test="not($tokens or $items)"/><!-- No remaining tokens or items, abort --> <xsl:when test="not($tokens)"><!-- No remaining tokens for current item, get next --> <xsl:variable name="att" select="($items[1]/ancestor-or-self::*/@attrib)[last()]"/> <xsl:call-template name="items-by-token"> <xsl:with-param name="items" select="$items[position() > 1]"/> <xsl:with-param name="tokens" select="concat(normalize-space(translate($att, ',', ' ')), ' ')"/> <xsl:with-param name="seen" select="$seen"/> </xsl:call-template> </xsl:when> <xsl:otherwise><!-- Process next token --> <xsl:variable name="att" select="substring-before($tokens, ' ')"/> <xsl:variable name="search" select="concat(' ', $att, ' ')"/> <xsl:variable name="new" select="not(contains($seen, $search))"/> <xsl:variable name="seen-add"> <xsl:if test="$new"><xsl:value-of select="concat($att, ' ')"/></xsl:if> </xsl:variable> <xsl:if test="$new"> <xsl:value-of select="concat(' Attrib: ', $att, ' ')"/> <xsl:for-each select="//bottomlevel[@name][contains(concat(' ', normalize-space(translate((ancestor-or-self::*/@attrib)[last()], ',', ' ')), ' '), $search)]"> <xsl:value-of select="concat('- ', @name, ' ')"/> </xsl:for-each> </xsl:if> <xsl:call-template name="items-by-token"> <xsl:with-param name="items" select="$items"/> <xsl:with-param name="tokens" select="substring-after($tokens, ' ')"/> <xsl:with-param name="seen" select="concat($seen, $seen-add)"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> -Brandon :) On Wed, Dec 29, 2010 at 10:25 PM, vesse <vessep@xxxxxxxxx> wrote: > Hi, > > I have an XML document that looks roughly like this: > <root> > <toplevel attrib="123"> > <midlevel attrib="453,123"> > <bottomlevel attrib="853,123" name="MyName"/> > <bottomlevel name="OtherItem"/> > > I need to group the bottomlevel items under each unique attribute ID. > Attribute on the lowest level found is the one that's important ( > (ancestor-or-self::/@attrib)[last()] ). So in the above example the > output would be > > Attrib:853 > - MyName > > Attrib: 123 > - MyName > - OtherItem > > Attrib: 453 > - OtherItem > > In the old days the attribute value was not CSV data so I used > > <xsl:key name="attribs" match="*" use="@attrib"/> > <xsl:for-each select="*[generate-id()=generate-id(key('attribs', @attrib)[1])]"> > > to go through the items by the attribute values. This does not of > course produce the wanted output anymore. Is it anyway possible to get > the unique values from the CSV data to work with, and then be also > able to find the bottomlevel items that have the current ID? I'm using > XSLT 1.0 (transformation done in browser). Changing the XML file > structure is out of the question. > > > BR, > Vesse
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] replacing nodes during xs, Andrew Welch | Thread | [xsl] sort problem, Terry Ofner |
[xsl] replacing nodes during xsl:co, Mark Anderson | Date | Re: [xsl] replacing nodes during xs, Michael Kay |
Month |