xsl-list
[Top] [All Lists]

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

2003-08-26 14:14:30
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(_at_)lists(_dot_)mulberrytech(_dot_)com 
[mailto:owner-xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com] On Behalf Of 
Brook Ellingwood
Sent: 26 August 2003 18:19
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: Passing element nodes through string functions (WAS 
RE: [xsl]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="'&#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



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



<Prev in Thread] Current Thread [Next in Thread>