Subject: Re: [xsl] creating list from structured paragraphs From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Mon, 20 May 2002 13:20:56 +0100 |
Hi David, >> >I'm hoping this is simple. Here is the XML: >> > >> ><doc> >> > <para>The following text is a list >> > <para-1>List item No. 1</para-1> >> > <para-1>List item No. 2</para-1> >> > <para-1>List item No. 3</para-1> >> > </para> >> ></doc> >> > >> >I need: >> > >> ><doc> >> > <para>The following text is a list >> > <list> >> > <list-item>List item No. 1</list-item> >> > <list-item>List item No. 2</list-item> >> > <list-item>List item No. 3</list-item> >> > </list> >> > </para> >> ></doc> If all your paras are in that structure, then you could use: <xsl:template match="para"> <para> <xsl:value-of select="text()" /> <list> <xsl:for-each select="para-1"> <list-item><xsl:apply-templates /></list-item> </xsl:for-each> </list> </para> </xsl:template> If your para elements hold a mixture of text nodes and para-1 elements intermingled (i.e. several lists, or text appearing before and after lists), then you need to use a grouping method. I favour a step-by-step method in these cases -- apply templates to the first node of the para element: <xsl:template match="para"> <para> <xsl:apply-template select="(text() | *)[1]" mode="para" /> </para> </xsl:template> Then, for text nodes, just give the value of the text node and move on to the next node: <xsl:template match="text()" mode="para"> <xsl:value-of select="." /> <xsl:apply-templates select="following-sibling::*[1]" mode="para" /> </xsl:template> For para-1 elements, if you've applied templates in para mode then you need to create a list, then step through the following para-1 elements to create the content of the list. After creating the list, apply templates to the next text node (or element) that isn't a para-1 element: <xsl:template match="para-1" mode="para"> <list> <xsl:apply-templates select="." mode="list-item" /> </list> <xsl:apply-templates mode="para" select="following-sibling::node()[not(self::para-1)][1]" /> </xsl:template> <xsl:template match="para-1" mode="list-item"> <list-item> <xsl:apply-templates /> </list-item> <xsl:apply-templates mode="list-item" select="following-sibling::node()[1][self::para-1]" /> </xsl:template> --- The XSLT 2.0 method is to group adjacent sets of nodes, and have the grouping value oscillate between true and false -- true when the node is a para-1 element and false when it isn't: <xsl:template match="para"> <xsl:for-each-group select="node()" group-adjacent="self::para-1"> <xsl:choose> <xsl:when test="self::para-1"> <list> <xsl:apply-templates select="current-group()" /> </list> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="current-group()" /> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </xsl:template> <xsl:template match="para-1"> <list-item> <xsl:apply-templates /> </list-item> </xsl:template> I suspect that this is a pattern we'll see quite a lot of in XSLT 2.0. It's a little non-obvious at first (though no more non-obvious than the grouping hoops that we have to jump through in XSLT 1.0). Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] creating list from struct, David Santamauro | Thread | RE: [xsl] creating list from struct, David Santamauro |
RE: [xsl] creating list from struct, David Santamauro | Date | RE: [xsl] creating list from struct, David Santamauro |
Month |