Subject: RE: [xsl] Building a hierarchy based on siblings From: Ryan Graham <Ryan.Graham@xxxxxxxxxxxxx> Date: Fri, 11 Jun 2004 12:59:04 -0700 |
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.david@xxxxxxxxxx] Sent: Thursday, June 10, 2004 9:34 PM To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx 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.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> --+-- --+------------------------------------------------------------------ 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 -> |
---|---|---|
Announce: Public XSLT/XSL-FO traini, G. Ken Holman | Thread | Troubles using Inodata Isogen Saxon, Markus Gamperl |
Announce: Public XSLT/XSL-FO traini, G. Ken Holman | Date | Troubles using Inodata Isogen Saxon, Markus Gamperl |
Month |