Re: [xsl] HTML: unordered list within unordered list

Subject: Re: [xsl] HTML: unordered list within unordered list
From: "Joerg Heinicke" <joerg.heinicke@xxxxxx>
Date: Sun, 28 Apr 2002 13:56:43 +0200
Hello Rich,

again unstructured XML, again unordered list ... deja vu?

The problem with your code are the <xsl:call-template/>. In my eyes they are
not good, especially for such tasks. Maybe it's impossible with
<xsl:call-template/>, but I didn't try. I think you should have a look at
<xsl:apply-templates/> and <xsl:template match=""/>. It's important to
understand the template driven approach of XSLT.

As in my last mail an half hour ago I use again <xsl:key/>. This time the
Muenchian Method for grouping elements as described on Jeni's page at
http://www.jenitennison.com/xslt/index.xml (or many examples in the archives
of the list).

At first I group the <Property>s by their number (without a or b or ...).
For this everything else is translated to ''. You could write translate(.,
'abcdef...', '') too, but the version with first translation of '1234...' to
nothing should be shorter.
All <Property>s are now in a group with their number as key.

<xsl:key name="items" match="Property" use="translate(., translate(.,
'1234567890', ''), '')"/>

<xsl:template match="root">
    <ul>
<!-- The Muenchian Method itself. The first element of every group is
selected. -->
        <xsl:apply-templates select="
        Property[
            count( . |
                key('items',
                    translate(., translate(., '1234567890', ''), '')
                )[1]
            ) = 1
        ]
        "/>
    </ul>
</xsl:template>

<xsl:template match="Property">
<!-- create the number -->
    <xsl:variable name="item-number" select="translate(., translate(.,
'1234567890', ''), '')"/>
<!-- if you need type="circle" add it here -->
    <li><xsl:value-of select="."/></li>
<!-- if there are more <Property>s with the same number and if it's not
already the second level -->
    <xsl:if test="count(key('items', $item-number)) > 1
        and not(normalize-space(substring-after(., $item-number)))">
        <ul>
<!-- select all <Property>s with this number except level 1 (the first
<Property> with this number) -->
            <xsl:apply-templates select="key('items',
$item-number)[position()!=1]"/>
        </ul>
    </xsl:if>
</xsl:template>

Regards,

Joerg


----- Original Message -----
From: "Rich Garcia" <rchgrca@xxxxxxxxx>


> Folks,
>
> I'm trying to generate the following HTML output:
> <ul>
>   <li>item1</li>
>   <li>item2</li>
>   <li>
>     <ul>
>       <li type="circle">item2a</li>
>       <li type="circle">item2b</li>
>     <ul>
>   </li>
>   <li>item3</li>
>   <li>item4</li>
> </ul>
>
> My xml looks like:
> <Property type="bullet">item1</Property>
> <Property type="bullet">item2</Property>
> <Property type="bullet"
> icon="circle">item2a</Property>
> <Property type="bullet"
> icon="circle">item2b</Property>
> <Property type="bullet">item3</Property>
> <Property type="bullet">item4</Property>
>
> My templates look like:
>
> <xsl:call-template name="showbullets"/>
>
> <xsl:template name="showbullets">
>   <xsl:if test="Property/@type = 'bullet'">
>     <xsl:call-template name="ul"/>
>   </xsl:if>
> </xsl:template>
>
> <!-- creates <ul> -->
> <xsl:template name="ul">
>   <ul><xsl:call-template name="li"/></ul>
> </xsl:template>
>
> <!-- creates unorder list bullets <li> -->
> <xsl:template name="li">
>   <xsl:for-each select="Property">
>     <li>
>       <xsl:if test="@icon='circle'">
>         <xsl:attribute
> name="type">circle</xsl:attribute>
>       </xsl:if>
>       <xsl:value-of select="@name"/><xsl:value-of
> select="."/><xsl:text> </xsl:text><xsl:value-of
> select="@yeargraduated"/>
>     </li>
>   </xsl:for-each>
> </xsl:template>
>
> Any suggestions?  I'm drawing a blank...


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread