Subject: RE: Passing element nodes through string functions (WAS RE: Preserving inline elements when using string functions)
From: "Michael Kay" <mhk@xxxxxxxxx>
Date: Tue, 26 Aug 2003 22:14:30 +0100
|
It's certainly a tricky one. I think the key is that instead of the
recursive call passing "substring-after", it has to pass (a) the
substring after the newline in the current text node, plus (b) the
following sibling nodes. This is probably a lot easier in 2.0 where you
can pass a heterogeneous sequence, but I think you can probably do it in
1.0 with two parameters, a string and a node-set. If the string is
empty, you look at the node-set; if the first node is an element, you
copy it out; if the first node is a text node, you look for newlines in
it.
Michael Kay
> -----Original Message-----
> From: owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> [mailto:owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx] On Behalf Of
> Brook Ellingwood
> Sent: 26 August 2003 18:19
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: Passing element nodes through string functions (WAS
> RE: Preserving inline elements when using string functions)
>
>
> Hi,
>
> I'm pretty close to deciding that what I'm trying to do is
> impossible, but before I give I'm going to try rephrasing my
> question and see if anyone has any ideas. Apologies for
> taking up bandwidth by reposting.
>
> I have elements containing PCDATA in the form of strings plus
> child elements, which contain strings and have attributes.
>
> <page>
> <bodytext>This is the <link url="">link</link>
> This is another line</bodytext>
> </page>
>
> I am serially applying two templates to these elements. The
> first template transforms the <link> element into an HTML <a
> href> element. The second template takes the output from the
> first template, identifies the sections of text set apart by
> CR/LF and surrounds them with an HTML <div> element. The
> problem I am having is that the "substring-before" and
> "substring-after" functions in the second template cause the
> child elements (the post-transform <a href> tags) to be
> discarded. Here is the XSL:
>
> <!-- begin a href transforms -->
>
> <xsl:template name="embeddedLinks">
> <xsl:apply-templates select="./node()"/>
> </xsl:template>
>
> <xsl:template match="link">
> <a style="text-decoration:underline"><xsl:attribute
> name="href"><xsl:value-of select="@url"/></xsl:attribute><xsl:value-of
> select="."/></a>
> </xsl:template>
>
> <!-- begin div transforms -->
>
> <xsl:template name="paragraphs">
> <xsl:param name="string" />
> <xsl:param name="linebreak" select="'
'" />
> <xsl:param name="divClass" />
> <xsl:choose>
> <xsl:when test="contains($string, $linebreak)">
> <DIV><xsl:attribute name="class"><xsl:value-of
> select="$divClass" /></xsl:attribute>
> <xsl:copy-of
> select="substring-before($string, $linebreak)" />
> </DIV>
> <xsl:call-template name="paragraphs">
> <xsl:with-param name="string"
>
> select="substring-after($string, $linebreak)" />
> <xsl:with-param name="linebreak"
> select="$linebreak" />
> <xsl:with-param name="divClass" select="$divClass" />
> </xsl:call-template>
> </xsl:when>
> <xsl:otherwise>
> <DIV><xsl:attribute name="class"><xsl:value-of
> select="$divClass" /></xsl:attribute>
> <xsl:copy-of select="$string" />
> </DIV>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:template>
>
> <!-- begin template calls and outputting -->
>
> Test 1: Links<br/>
> <xsl:for-each select="./page/bodytext">
> <xsl:call-template name="embeddedLinks" />
> </xsl:for-each>
>
> <br/><br/>Test 2: Paragraphs<br/>
> <xsl:for-each select="./page/bodytext">
> <xsl:call-template name="paragraphs">
> <xsl:with-param name="divClass" select="'para'" />
> <xsl:with-param name="string">
> <xsl:copy-of select="."/>
> </xsl:with-param>
> </xsl:call-template>
> </xsl:for-each>
>
> <br/>Test 3: Links and Paragraphs<br/>
> <xsl:for-each select="./page/bodytext">
> <xsl:call-template name="paragraphs">
> <xsl:with-param name="divClass" select="'para'" />
> <xsl:with-param name="string" >
> <xsl:call-template name="embeddedLinks" />
> </xsl:with-param>
> </xsl:call-template>
> </xsl:for-each>
>
>
> As you can see, I've got three different output tests to
> check each stage of the transform. Here is my output (cleaned
> up slightly for readability):
>
> Test 1: Links<br>
> This is the <a style="text-decoration:underline" href="">link</a>
> This is another line<br>
>
> <br>Test 2: Paragraphs<br>
> <DIV class="para">This is the link</DIV>
> <DIV class="para"> This is another line</DIV>
>
> <br>Test 3: Links and Paragraphs<br>
> <DIV class="para">This is the link</DIV>
> <DIV class="para"> This is another line</DIV>
>
> I could get around this by making any elements in the XML
> that will have contents like this into CDATA, but to my way
> of thinking, that's like putting processing instructions in
> the XML. I'd rather keep it pure and do the work on the XSL
> side. But, as I said, I'm starting to think this may be
> impossible. If anyone thinks differently, I'd love to hear from them.
>
> Thanks,
>
> -- Brook
>
>
> XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
>
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
|