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

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


Subject: [xsl] Re: Passing element nodes through string functions (WAS RE: [xsl] Preserving inline elements when using string functions)
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Tue, 26 Aug 2003 14:00:15 -0400

Brook,

Sorry I haven't been able to post on this interesting problem. One is always reluctant to say something is impossible. (And I've been very busy.)

Yet it does appear that you are trying to do two mutually exclusive things at once:

1. Process elements that contain arbitrary mixed content as strings, to perform string operations on them (in your case, splitting out and wrapping substrings).

2. Process elements that contain arbitrary mixed content as trees of nodes, so you can represent their mixed content in appropriate ways in the output.

You can't do both these things at once on the same element.

You can, however, get the results you want, or at least something close, if you do the two things in two separate passes.

If you are willing to use a node-set() extention function, or XSLT 2.0, you can even run these two passes in a single run of a stylesheet. (Nonetheless I'd first build them to run separately, just to keep myself sane.)

When you do this, you'll have to decide which process comes first; the best answer to this depends on your data and requirements. Particularly, you'll have to consider what you want to happen if your mixed content elements ever happen to split strings which you are also trying to wrap.... the presence of elements in mixed content may prevent your string-wrapping from working if you're not content just to throw away the inline elements.

Cheers,
Wendell

At 01:19 PM 8/26/2003, you wrote:
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


======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


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




Current Thread
Keywords