Re: [xsl] Nested lists

Subject: Re: [xsl] Nested lists
From: Terry Badger <terry_badger@xxxxxxxxx>
Date: Thu, 7 Nov 2013 06:02:24 -0800 (PST)
Rick,
Here is another way to look at the problem which identifies the first
potential list item and uses that to start an ordered list. The call-template
works it way forward outputting list items that have the same class value. I
did not go further to see how to use this for the sub lists.
<?xml
version="1.0" encoding="UTF-8"?>
<xsl:stylesheetxmlns:xsl="http://www.w3.org/1999/XSL/Transform"version="1.0";
xmlns:xhtml="http://www.w3.org/1999/xhtml";>
<xsl:outputindent="yes"/>
<xsl:strip-spaceelements="*"/>
<!-- turn off defaults -->
<xsl:templatematch="*|@*"/>
<!-- main start -->
<xsl:templatematch="/">
<xsl:apply-templates/>
</xsl:template>
<!-- push through all elements except p
with a list class -->
<xsl:templatematch="xhtml:html | xhtml:head | xhtml:body
| xhtml:p | xhtml:h2">
<xsl:elementname="{local-name()}">
<xsl:copy-ofselect="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!-- this is a list item -->
<xsl:templatematch="xhtml:p[contains(@class , 'list')]">
<xsl:choose>
<!--
first list item -->
<xsl:whentest="preceding-sibling::*[1][not(contains(@class
, 'list'))]">
<xsl:elementname="ol">
<xsl:call-templatename="look-forward">
<xsl:with-paramname="first"select="."/>
<xsl:with-paramname="here"select="."/>
</xsl:call-template>
</xsl:element>
</xsl:when>
<!-- not first list item -->
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
<!-- that template looks
forward one at a time on the p to extract and output the list items -->
<xsl:templatename="look-forward">
<xsl:paramname="first"/>
<xsl:paramname="here"/>
<xsl:choose>
<xsl:whentest="$here/self::xhtml:p[contains(@class , 'list')] and
$first/@class = $here/@class">
<xsl:elementname="li">
<xsl:copy-ofselect="@*"/>
<xsl:apply-templatesselect="$here/node()"/>
</xsl:element>
<xsl:call-templatename="look-forward">
<xsl:with-paramname="first"select="$first"/>
<xsl:with-paramname="here"select="$here/following-sibling::*[1]"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

Terry


On Friday, November 1, 2013 3:43
PM, Rick Quatro <rick@xxxxxxxxxxxxxx> wrote:

Hi Michael,

Thanks for the
excellent advice.

Rick

-----Original Message-----
From: Michael
MC<ller-Hillebrand [mailto:mmh@xxxxxxxxx] 
Sent: Friday, November 01, 2013
12:37 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Nested lists
Hi Rick,

Compared to the pain using XSLT1 for a task which XSLT2 can easily
handle,
the pain you have to go through if you are forced to change a nice
working
XSLT2 solution down to XSLT1 is a real PITA.

But anyhow, I know that
sometimes we are forced to do ugly stuff. I would
not be trying to use xsl:key
for that problem, as keys are more of an index
across a full document and in
your situation everything depends on the order
of elements. In XSLT2 you would
use xsl:for-each-group, which in XSLT1
sometimes can be kind-of replicated by
"tree walking"
<http://www.dpawson.co.uk/xsl/sect2/N4486.html#d5510e1105>.

As
in your example the same class attribute value maybe used for a level 1
or
level 2 list item, it might also be a good idea to do some preprocessing,
because otherwise some XPaths may become really long. I guess I would try to
separate the logic of finding the correct list item level from the step of
adding the required <ul>.

Good luck,

- Michael


Am 31.10.2013 um 21:22
schrieb Rick Quatro <rick@xxxxxxxxxxxxxx>:

> Hi,
> 
> I have this for my
input XML:
> 
> <body>
>B  <p class="listintro">ListItem_Bullets:</p>
>B  <p
class="listitembullets">b" Item 1</p>B  <p 
> class="listitembullets">b"
Item 2</p>B  <p 
> class="listitembullets">b" Item 3</p>B  <p 
>
class="normal">Paragraph within a list.</p>B  <p 
>
class="listitembullets">b" Item 4</p>B  <p 
> class="listitembullets">b"
Item 5</p>B  <p 
> class="listitemindented">b" Item 1 indented</p>B  <p 
>
class="listitemindented">b" Item 2 indented</p>B  <p 
>
class="listitembullets">b" Item 6</p>B  <h2>Indented list starts 
>
here:</h2>B  <p class="listitemindented">b" Item 1 indented</p>B  
> <p
class="listitemindented">b" Item 2 indented</p>B  <p 
>
class="listitemindented">b" Item 3 indented</p>B  <p 
>
class="normal">Paragraph within a list.</p>B  <p 
>
class="listitemindented">b" Item 4 indented</p>B  <p 
>
class="listitemindented">b" Item 5 indented</p>B  <p 
>
class="listitemindented">b" Item 6 indented</p> </body>
> 
> I want to get
this:
> 
> <body>
>B  <p class="listintro">ListItem_Bullets:</p>
>B  <ul>
>B 
B B B <li>Item 1</li>
>B  B B B <li>Item 2</li>
>B  B B B <li>Item 3</li>
>B 
</ul>
>B  <p class="normal">Paragraph within a list.</p>B  <ul>
>B 
B B B <li>Item 4</li>
>B  B B B <li>Item 5</li>
>B  B B B <ul>
>B  B 
B B B <li>Item 1 indented</li>
>B  B  B B B <li>Item 2 indented</li>
>B 
B B B </ul>
>B  B B B <li>Item 6</li>
>B  </ul>
>B  <h2>Indented list starts
here:</h2>
>B  <ul>
>B  B B B <li>. Item 1 indented</li>
>B  B B B <li>. Item
2 indented</li>
>B  B B B <li>. Item 3 indented</li>
>B  </ul>
>B  <p
class="normal">Paragraph within a list.</p>B  <ul>
>B  B B B <li>. Item 4
indented</li>
>B  B B B <li>. Item 5 indented</li>
>B  B B B <li>. Item 6
indented</li>
>B  </ul>
> </body>
> 

--
Michael MC<ller-Hillebrand
mmh@xxxxxxxxx

Current Thread