Thank you so much for the guidance -- you filled the knowledge gap on this
one! I created a modified version based on what you posted below. It
integrates seamlessly into my existing stylesheet and provides the correct
output :)
<xsl:template match="para[not(starts-with(., '* '))]">
<para>
<xsl:apply-templates/>
</para>
</xsl:template>
<xsl:template match="para[starts-with(., '* ') and
not(preceding-sibling::para[1][starts-with(.,'* ')])]">
<xsl:variable name="followingParagraph"
select="following-sibling::para[not(starts-with(., '* '))][1]"/>
<itemizedlist mark="bullet">
<xsl:apply-templates select=". |
following-sibling::para[starts-with(.,'* ') and not(preceding-sibling::para
= $followingParagraph)]" mode="list"/>
</itemizedlist>
</xsl:template>
<xsl:template match="para[starts-with(.,'* ') and
preceding-sibling::para[1][starts-with(.,'* ')]] "/>
<xsl:template match="para" mode="list">
<listitem>
<xsl:apply-templates select="text() | *"/>
</listitem>
</xsl:template>
<xsl:template match="text()[starts-with(., '* ')]">
<xsl:value-of select="substring-after(., '* ')"/>
</xsl:template>
Thanks again!
-Ryan
-----Original Message-----
From: M. David Peterson [mailto:m(_dot_)david(_at_)mdptws(_dot_)com]
Sent: Thursday, June 10, 2004 9:34 PM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: RE: [xsl] Building a hierarchy based on siblings
Hey Ryan,
Kind of an interesting situation that has several possible solutions. But
from your comments it seems that getting a good grasp of how to properly use
recursion to build nested output is something you are in seek of. So I gave
you an example that uses as much recursion as possible to help you in your
quest :)
I was going to try and comment it a bit but I actually just realized the
time and I need to head out for a bit so I can attend a buddy of mines
bachelor party. But I don't plan on drinking too much so when I return Ill
look to see if you had any questions. Otherwise, enjoy! I hope you find
this helpful in better understanding how you can use recursion in multiple
ways in XSLT.
Best of luck!
<M:D/>
Heres the XSLT:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:element name="sect1">
<xsl:apply-templates select="sect1/para[not(starts-with(.,'* '))]"
mode="normal"/>
</xsl:element>
</xsl:template>
<xsl:template match="para" mode="normal"><!-- no pun intended. I like
X-Files but not so much I name my attribute values to match the shows focus
;) --> <xsl:variable name="followingParagraph"
select="following-sibling::para[not(starts-with(., '*'))][1]"/>
<xsl:copy-of select="."/>
<xsl:if test="following-sibling::para[1][starts-with(., '* ')]">
<xsl:element name="itemizedlist">
<xsl:apply-templates
select="following-sibling::para[starts-with(.,'* ') and
not(preceding-sibling::para = $followingParagraph)]" mode="buildList"/>
</xsl:element>
</xsl:if>
</xsl:template>
<xsl:template match="para" mode="buildList">
<xsl:element name="listitem">
<xsl:element name="para">
<xsl:apply-templates select="text() | *"/>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="text()[starts-with(., '* ')]">
<xsl:value-of select="substring-after(., '* ')"/> </xsl:template>
<xsl:template match="text() | *">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
Heres the transformed result of the XML you gave as an example:
<?xml version="1.0" encoding="UTF-8"?>
<sect1>
<para>First Paragraph</para>
<itemizedlist>
<listitem>
<para>First list item</para>
</listitem>
<listitem>
<para>Second list item</para>
</listitem>
<listitem>
<para>Third list item <emphasis>emphasized text</emphasis>
</para>
</listitem>
</itemizedlist>
<para>Second Paragraph</para>
<para>Third paragraph</para>
<itemizedlist>
<listitem>
<para>First list item #2</para>
</listitem>
<listitem>
<para>Second list item #2</para>
</listitem>
</itemizedlist>
<para>Another paragraph</para>
</sect1>
Enjoy! I'm off to get a little loopy 8$ but will return before to long so
don't hesitate to ask questions... Worst case Ill get back to you in the
morning.
-----Original Message-----
From: Ryan Graham [mailto:Ryan(_dot_)Graham(_at_)apollogrp(_dot_)edu]
Sent: Thursday, June 10, 2004 7:35 PM
To: 'xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com'
Subject: [xsl] Building a hierarchy based on siblings
Hi all,
I am having some trouble getting the correct template matches written to
build a hierarchy.
I have similar to the following input XML:
<sect1>
<para>First Paragraph</para>
<para>* First list item</para>
<para>* Second list item</para>
<para>* Third list item <emphasis>emphasized text</emphasis></para>
<para>Second Paragraph</para>
<para>Third paragraph</para>
<!-- Start new list-->
<para>* First list item #2</para>
<para>* Second list item #2</para>
<para>Another paragraph</para>
</sect1>
I would like to put all para nodes that begin with "* " into a list
structure and cut off the first two characters when processed, to get the
following output:
<para>First Paragraph</para>
<itemizedlist>
<listitem>
<para>First list item</para>
</listitem>
<listitem>
<para>Second list item</para>
</listitem>
<listitem>
<para>Third list item <emphasis>emphasized
text</emphasis></para>
<listitem>
</itemizedlist>
<para>Second Paragraph</para>
<para>Third paragraph</para>
<itemizedlist>
<listitem>
<para>First list item #2</para>
</listitem>
<listitem>
<para>Second list item #2</para>
</listitem>
</itemizedlist>
<para>Another paragraph</para>
I was using this to get the <listitems> built:
<xsl:template match="para">
<xsl:choose>
<xsl:when test="substring(node()[1], 0, 3) = '* '>
<itemizedlist>
<listitem>
<xsl:value-of select="substring(node()[1], 3)"/>
<xsl:apply-templates select="node()[position() > 1]"/>
</listitem>
</itemizedlist>
</xsl:when>
<xsl:otherwise>
<para>
<xsl:apply-templates/>
</para>
</xsl:otherwise>
</xsl:template>
But with this match, every <para> that starts with "* " becomes its own
itemizedlist with one listitem. Is there an efficient way to do this using
a recursive template, without creating duplicate output?
I appreciate any and all suggestions!
Thanks,
Ryan
--+------------------------------------------------------------------
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>
--+--