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