Subject: RE: [xsl] Building a hierarchy based on siblings From: "M. David Peterson" <m.david@xxxxxxxxxx> Date: Thu, 10 Jun 2004 22:33:41 -0600 |
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.Graham@xxxxxxxxxxxxx] Sent: Thursday, June 10, 2004 7:35 PM To: 'xsl-list@xxxxxxxxxxxxxxxxxxxxxx' 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@xxxxxxxxxxxxxxxxxxxxxx> --+--
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Building a hierarchy based on sibli, Ryan Graham | Thread | xsl:variable and key, Sameer N |
Re: [xsl] xsl:variable and key, G. Ken Holman | Date | XPathAPI question, Ling Kok Choon |
Month |