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

Re: [xsl] Processing tag text either side of nested tags


Subject: Re: [xsl] Processing tag text either side of nested tags
From: "andrew welch" <andrew.j.welch@xxxxxxxxx>
Date: Tue, 11 Apr 2006 15:53:02 +0100

On 4/11/06, Neil Crofts <neil.crofts@xxxxxxxxx> wrote:
> I have some XML with text contained either side of a nested tag. I
> would like to apply a named template to the text parts such that I
> modify the text but also preserve the nested tags as-is. For example,
> I have some XML of the form:
>
> <outer> hello there <inner name="alpha">beta gamma</inner> goodbye then
</outer>
>
> ...and I need to transform it to the following format:
>
> <outer> HELLO THERE <inner name="alpha">beta gamma</inner> GOODBYE THEN
</outer>
>
> where in this case a named template converts the text to upper case,
> although ideally the conversion function would be arbitrary.
>
> I have made a number of attempts so far at doing this, but without
> success. For example:
>
>     <!-- Identity template -->
>     <xsl:template match="@*|node()">
>         <xsl:copy>
>             <xsl:apply-templates select="@*|node()"/>
>         </xsl:copy>
>     </xsl:template>
>
>     <!-- Outer template -->
>     <xsl:template match="outer">
>         <xsl:copy>
>             <xsl:copy-of select="@*"/>
>             <xsl:call-template name="upper">
>                 <xsl:with-param name="text">
>                     <xsl:apply-templates select="node()"/>
>                 </xsl:with-param>
>             </xsl:call-template>
>         </xsl:copy>
>     </xsl:template>
>
>     <!-- Convert text to upper case -->
>     <xsl:template name="upper">
>         <xsl:param name="text"/>
>         <xsl:value-of select="translate($text,
> 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
>     </xsl:template>
>
>
> The above results in:
>
> <outer>HELLO THEREBETA GAMMAGOODBYE THEN</outer>
>
> I understand why this is producing that, but I just can't figure out
> how to apply the named template to only the text parts of the <outer>
> tag, while copying the nested <inner> tag as-is.

Change your outer template to this:

   <!-- Outer template -->
   <xsl:template match="outer/text()">
           <xsl:call-template name="upper">
               <xsl:with-param name="text" select="."/>
           </xsl:call-template>
   </xsl:template>

This only calls the upper-case template for the text nodes of <outer>
leaving the identity template to copy the nested <inner> node (which
is pretty much a copy of your last paragraph :)

cheers
andrew


Current Thread
Keywords
xml