[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Passing element nodes through string functions (WAS RE: [xsl] Preserving inline elements when using string functions)


Subject: Passing element nodes through string functions (WAS RE: [xsl] Preserving inline elements when using string functions)
From: Brook Ellingwood <brook@xxxxxxxxxxx>
Date: Tue, 26 Aug 2003 10:19:28 -0700

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="'&#xA;'" />
       <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



Current Thread
Keywords