Subject: Re: [xsl] empty elements to filled without overlapping hierachies From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Wed, 12 Nov 2003 13:25:04 +0000 |
Hi James, > What I'm wondering is what sort of strategy one could use in > XSLT (including XSLT2) to change these to filled tags. e.g.: > <Q value="WELBORNE." > NO BOUZE? NOR NO TOBACCO?</Q> Let's try to find an XSLT 2.0 solution. It will use <xsl:for-each-group> with the group-starting-with option, which groups together items such that each group starts with the same thing. When we match the <body> element, we want to copy it and its <TITLE> child: <xsl:template match="body"> <body> <xsl:copy-of select="TITLE" /> ... </body> </xsl:template> The first level of grouping is <SN>s. We want to group all the child nodes of the <body> element, aside from the <TITLE> element, into groups that start with a particular <SN> element. For each of these groups, we want to create a <SN> element with the value attribute from the original <SN>: <xsl:template match="body"> <body> <xsl:copy-of select="TITLE" /> <xsl:for-each-group select="node() except TITLE" group-starting-with="SN"> <SN value="{@value}"> ... </SN> </xsl:for-each-group> </body> </xsl:template> Next, we want to take the elements in that group (aside from the <SN> element itself) and group them into groups starting with <Q> elements. Now, there are three possible arrangements of these groups: 1. The very first group might not start with a <Q> element; in that case, we just want to copy all the items in that group. 2. The group might end with a <SSD> element, in which case we want to have a <Q> element that contains all the items in the group aside from that final <SSD> element (and the <Q> element itself). 3. The group might end with something other than a <SSD> element, in which case we want to have a <Q> element that contains all the items in the group aside from the <Q> element itself <xsl:template match="body"> <body> <xsl:copy-of select="TITLE" /> <xsl:for-each-group select="node() except TITLE" group-starting-with="SN"> <SN value="{@value}"> <xsl:for-each-group select="current-group() except ." group-starting-with="Q"> <xsl:choose> <xsl:when test="not(self::Q)"> <xsl:copy-of select="." /> </xsl:when> <xsl:when test="current-group()[last()][self::SSD]"> <Q value="{@value}"> <xsl:copy-of select="(current-group() except .) [position() != last()]" /> </Q> <xsl:copy-of select="current-group()[last()]" /> </xsl:when> <xsl:otherwise> <Q value="{@value}"> <xsl:copy-of select="current-group() except ." /> </Q> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </SN> </xsl:for-each-group> </body> </xsl:template> This assumes that whitespace-only text nodes have been stripped from the input tree using: <xsl:strip-space elements="body" /> and the output looks best if you then include: <xsl:output indent="yes" /> An XSLT 1.0 solution would be harder... 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 -> |
---|---|---|
[xsl] empty elements to filled with, James Cummings | Thread | Re: [xsl] empty elements to filled , David Carlisle |
Re: [xsl] simple question: <fo: and, David Carlisle | Date | Re: [xsl] Check if text is before , David Carlisle |
Month |