|
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 |