xsl-list
[Top] [All Lists]

Re: [xsl] CSV data in attribute - how to get unique values?

2011-01-05 03:23:53
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[(_at_)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() &gt; 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('&#10;Attrib: ', $att, '&#10;')"/>
                                        <xsl:for-each 
select="//bottomlevel[(_at_)name][contains(concat(' ',
normalize-space(translate((ancestor-or-self::*/@attrib)[last()], ',',
' ')), ' '), $search)]">
                                                <xsl:value-of select="concat('- 
', @name, '&#10;')"/>
                                        </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(_at_)gmail(_dot_)com> 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

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>
  • Re: [xsl] CSV data in attribute - how to get unique values?, Brandon Ibach <=