Thanks for your detailed explanation, it helped a lot with my understanding.
Can you by any chance suggest any good books? Since I would like to get to
know more about XSLT 2.0
Graeme
--------------------------------------------------
From: "G. Ken Holman" <gkholman(_at_)CraneSoftwrights(_dot_)com>
Sent: Saturday, January 24, 2009 2:39 AM
To: <xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com>
Subject: Re: [xsl] Changing a Tree Walking, forward walk example
At 2009-01-24 01:04 +0000, Graeme Kidd wrote:
The problem is that my list does not have an end list node if a new list
starts immediately after an existing list. So for example this:
...
Needs to be changed to this:
...
I am finding it hard because I need to match a list node that does not
contain "End List" to start a list as well as end it. So far I have not
been able to detect if I am still in a list before a new list starts, in
which case I need to close it and start a new one.
That is a typical imperative programming approach that does not work well
with XML content. You are thinking about tags instead of thinking about
elements. In XSLT one cannot "close one off and start a new one", because
that implies one is able to "throw in an end tag and then a start tag".
When dealing with markup, this isn't an issue, but XSLT doesn't deal with
markup, it deals with nodes. I see this a lot in very poorly written XSLT
where novice users try to "end off a table row and start another" by
inappropriately using disable-output-escaping. That's fine in programming
where I'm serializing markup, but in XSLT one is constructing result
trees, not serializing markup (that's the responsibility of the XSLT
processor, not the stylesheet).
The approach you need must be more declarative. "How do I detect
everything that belongs in a list so that I can properly construct the
result tree list nodes?" Nothing there about tags, only about structures.
So, you need to look at your content and determine how to declaratively
express the presence of the lists. This is done for your example with
<xsl:for-each-group>, which I tell my students is better understood when
one reads the element name as if it were "for the first member of each
group".
Now, based on the nature of your data, your lists start with
"<list>...</list>" and they optionally end with "<list>End List</list>".
Another way to say that is a list starts with "<list>....</list>" and
non-lists start with "<list>End List</list>".
So this is how I approached it in the solution below ... I hope this
helps.
. . . . . . . . . . . ken
t:\ftemp>type kidd.xml
<document>
<p>Non List text</p>
<list>List Heading Type 1</list>
<p>First item</p>
<p>Second item</p>
<list>List Heading Type 2</list>
<p>First item</p>
<p>Second item</p>
<p>Third item</p>
<list>End List</list>
<p>Unrelated Text</p>
<p>Not in a list</p>
<list>List Heading Type 1</list>
<p>First item</p>
<list>End List</list>
<p>More Unrelated Text</p>
<p>Not in a list</p>
</document>
t:\ftemp>call xslt2 kidd.xml kidd.xsl
<?xml version="1.0" encoding="UTF-8"?>
<document>
<p>Non List text</p>
<list>
<li>First item</li>
<li>Second item</li>
</list>
<list>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</list>
<p>Unrelated Text</p>
<p>Not in a list</p>
<list>
<li>First item</li>
</list>
<p>More Unrelated Text</p>
<p>Not in a list</p>
</document>
t:\ftemp>type kidd.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="document">
<document>
<xsl:for-each-group select="*" group-starting-with="list">
<xsl:choose>
<xsl:when test="not(self::list)">
<!--there must be a group before the first list-->
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:when test=".='End List'">
<!--this indicates that what follows isn't in a list-->
<xsl:apply-templates select="current-group()[position()>1]"/>
</xsl:when>
<xsl:otherwise>
<!--we are starting a list-->
<list>
<xsl:for-each select="current-group()[position()>1]">
<li><xsl:apply-templates/></li>
</xsl:for-each>
</list>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</document>
</xsl:template>
<xsl:template match="@*|node()"><!--identity for all other nodes-->
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
t:\ftemp>rem Done!
--
Upcoming XSLT/XSL-FO, UBL and code list hands-on training classes:
: Sydney, AU 2009-01/02; Brussels, BE 2009-03; Prague, CZ 2009-03
Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video
Video lesson: http://www.youtube.com/watch?v=PrNjJCh7Ppg&fmt=18
Video overview: http://www.youtube.com/watch?v=VTiodiij6gE&fmt=18
G. Ken Holman mailto:gkholman(_at_)CraneSoftwrights(_dot_)com
Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/
Male Cancer Awareness Nov'07 http://www.CraneSoftwrights.com/s/bc
Legal business disclaimers: http://www.CraneSoftwrights.com/legal
--~------------------------------------------------------------------
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>
--~--