[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] Converting siblings to children of a node.


Subject: Re: [xsl] Converting siblings to children of a node.
From: Mark Brand <mark.brand@xxxxxxxxxxxxxxxxxxxx>
Date: Thu, 07 Aug 2003 11:40:47 +1000

Hi: Shawn:

I am not sure if you are in position to be using XSLT 2.0 (Saxon 7 is the only processor i believe) but if you are - You may want to have a look at the for-each-group element, there are also some good examples on using this element on the XSLT 2.0 TR on www.w3.org.

Thanks
Mark

Shawn O. McKenzie wrote:

I have a source document something like:

<longdesc>
 <para style="Normal">This is a regular paragraph.</para>
 <para style="Normal">So is this but what follows is a list:</para>
 <para style="LS1">Item one</para>
 <para style="LS1">Item two</para>
 <para style="Normal">This is a regular paragraph.</para>
 <para style="Normal">This is a regular paragraph.</para>
 <para style="Normal">This is a regular paragraph.</para>
 <para style="Normal">What follows is a list:</para>
 <para style="LS1">Item one</para>
 <para style="LS1">Item two</para>
 <para style="LS1">Item three</para>
 <para style="Normal">This is a regular paragraph.</para>
</longdesc>

I would like to translate this to something like

<p>This is a regular paragraph.</p>
<p>So is this but what follows is a list:</p>
<ul>
  <li>Item one<li>
  <li>Item two<li>
</ul>
<p>This is a regular paragraph.</p>
<p>This is a regular paragraph.</p>
<p>This is a regular paragraph.</p>
<p>What follows is a list:</p>
<ul>
  <li>Item one<li>
  <li>Item two<li>
  <li>Item three<li>
</ul>
<p>This is a regular paragraph.</p>


I thought I could do this with something like:


      <xsl:if test="@style='LS1'">
        <xsl:if test="not(preceding-sibling::para/@style='LS1')">
          <ul>
            <li><xsl:value-of select="."/></li>
        </xsl:if>

<xsl:if test="preceding-sibling::para/@style='LS1' and following-sibling::para/@style='LS1'">
<li><xsl:value-of select="."/></li>
</xsl:if>


<xsl:if test="preceding-sibling::para/@style='LS1' and not(following-sibling::para/@style='LS1')">
<li><xsl:value-of select="."/></li>
</ul>
</xsl:if>
</xsl:if>


But of course that won't work. Then, I thought I could do it with recursion, passing the current para element as a variable:

<xsl:template match="para[@style='LS1']">
 <xsl:if test="not(preceding-sibling::para[@style='LS1'])">
   <xsl:variable name="node">
     <xsl:copy-of select="."/>
   </xsl:variable>
   <ul>
     <xsl:call-template name="list">
       <xsl:with-param name="listitem" select="$node"/>
     </xsl:call-template>
   </ul>
 </xsl:if>
</xsl:template>

<xsl:template name="list">
 <xsl:param name="listitem"/>
 <li><xsl:value-of select="$listitem"/></li>
 <xsl:if test="following-sibling::para[@style='LS1']">
   <xsl:call-template name="list">
     <xsl:with-param name="listitem">
       <xsl:copy-of select="following-sibling::para"/>
     </xsl:with-param>
   </xsl:call-template>
 </xsl:if>
</xsl:template>


But that doesn't change the context to the preceding-sibling, so it loops.


Any suggestions?


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




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



Current Thread
Keywords