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

RE: [xsl] Change text on given node at runtime


Subject: RE: [xsl] Change text on given node at runtime
From: jeff.day@xxxxxx
Date: Thu, 24 Jul 2003 13:26:06 +0100

Thank you, Gentlemen both, but neither of these solutions got me any further
than I am already.

A example of my source XML is...

<A Attrib1="Z">
     <B>
         <R>text</R>
         <S Attrib2="Y">text</S>
     </B>
     <C>
         <E Attrib3="X">text
             <F>text</F>
             <G>
                 <H>text</H>
                 <J Attrib4="W">text</J>
             </G>
             <K>
                 <L>text</L>
                 <M>text</M>
             </K>
             <N>
                 <P Attrib5="V">text</P>
                 <Q>text</Q>
             </N>
         </E>
     </C>
</A>

(Basically any valid XML structure)

Our varied solutions all work down to the point of text replacement but do
not process children below that point. For example, if I want to change the
text at node <E>, this works successfully (including <E>), but all children
of <E>,  (i.e. <F>, <G> etc.) do not appear in the output.

So, my challenge is:  How do we continue processing down through all
children below the point of text replacement (so they appear in the output
unchanged from the original)?

Jeff 

-----Original Message-----
From: David Carlisle [mailto:davidc@xxxxxxxxx]
Sent: 24 July 2003 12:46
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Change text on given node at runtime




  Since you are using Xalan-J, i have used a Xalan
  extension function nodeset which helps me enumerate
  over the attributes.

You didn't need it there

   <xsl:for-each select="xalan:nodeset(@*)">

@* returns a node set so you could just have gone

   <xsl:for-each select="@*">

(since the input to xx:node-set() is supposed to be a
result-tree-fragment, I think some engines would actually error
if you pass in a node set.)

      <xsl:for-each select="xalan:nodeset(@*)">
	<xsl:variable name="attName" select="name(.)"/>
	<xsl:attribute name="{$attName}"><xsl:value-of
                select="."/></xsl:attribute>
      </xsl:for-each>

  since you are not changing the name or the value that whole loop could
  could be

<xsl:copy-of select="@*/>

In both branches of your template you are copying the element and all
its attributes, the only difference is whether to apply templates or to
insert the text param, so you can simplify by moving the element and
attribute handling to the shared part, ie:

   <xsl:template match="@* | node()">
      <xsl:if test="(name(.) = $tag)">
        <xsl:element name="{$tag}">
          <xsl:for-each select="xalan:nodeset(@*)">
   	<xsl:variable name="attName" select="name(.)"/>
   	<xsl:attribute name="{$attName}"><xsl:value-of
   select="."/></xsl:attribute>
         </xsl:for-each>
         <xsl:value-of select="$text"/>
        </xsl:element>
      </xsl:if>	     
   
      <xsl:if test="not(name(.) = $tag)">
        <xsl:copy>
   	<xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:if>
   </xsl:template>
   
   
can be simplified to:
   

<xsl:template match="*">
  <xsl:copy>
   <xsl:copy-of select="@*/>
    <xsl:choose>
      <xsl:when test="name()=$tag"><xsl:value-of select="$text"/></xsl:when>
      <xsl:otherwise><xsl:apply-templates/></xsl:otherwise>
    </xsl:choose>
  </xsl:copy>
</xsl:template>

David

________________________________________________________________________
This e-mail has been scanned for all viruses by Star Internet. The
service is powered by MessageLabs. For more information on a proactive
anti-virus service working around the clock, around the globe, visit:
http://www.star.net.uk
________________________________________________________________________

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


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



Current Thread
Keywords
xml