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