10

I'm trying to do something that seems like it should be very simple, but I can't get it working, and I can't seem to find any examples that don't involve lots of irrelevant things. I want to update the text content of a specific xml tag to a specific value (passed in as a parameter, this XSLT will be used from ant). A simple example :

I want to transform

<foo>
  <bar>
    baz
  </bar>
</foo>

To

<foo>
    <bar>
        something different
    </bar>
</foo>

This is the stylesheet that I tried, which results in just the tags, no text at all

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- identity transformation, to keep everything unchanged except for the stuff we want to change -->
    <!-- Whenever you match any node or any attribute -->
    <xsl:template match="node()|@*">
        <!-- Copy the current node -->
        <xsl:copy>
            <!-- Including any attributes it has and any child nodes -->
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- change the text of the bar node, in the real template the value won't be specified inline -->
    <xsl:template match="/foo/bar/">
        <xsl:param name="baz" value="something different"/>
            <xsl:value-of select="$baz"/>
    </xsl:template>
</xsl:stylesheet>

Thanks in advance!

3 Answers 3

16

There are a number of problems with the provided code which lead to compile-time errors:

<xsl:template match="/foo/bar/"> 
    <xsl:param name="baz" value="something different"/> 
        <xsl:value-of select="$baz"/> 
</xsl:template>
  1. The match pattern specified on this template is syntactically illegal -- an XPath expression cannot end with the / character.

  2. xsl:param cannot have an unknown attribute such as value

Solution:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pReplacement" select="'Something Different'"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="foo/bar/text()">
  <xsl:value-of select="$pReplacement"/>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the provided XML document:

<foo>
  <bar>
    baz
  </bar>
</foo>

the wanted, correct result is produced:

<foo>
   <bar>Something Different</bar>
</foo>
Sign up to request clarification or add additional context in comments.

Comments

0

A slightly different approach:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:param name="replace"/>

  <xsl:template match="node()|@*">
    <xsl:choose>
      <xsl:when test="text() and name(..)='bar' and name(../..)='foo'">
        <xsl:value-of select="$replace"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

Comments

-1
<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  version="1.0">
<xsl:output indent="yes" encoding="UTF-8" method="xml"/>
<xsl:param name="param-from-ant" as="xs:string"/>

<xsl:template match="node()|@*">
 <xsl:copy>
  <xsl:apply-templates select="@*|node()"/>
 </xsl:copy>
</xsl:template>

<xsl:template match="/foo/bar">
 <xsl:value-of select="$param-from-ant"/>
</xsl:template>
</xsl:stylesheet>

2 Comments

I tried that (both in my slightly more complex example, and on the base example), but in doesn't seem to work? I'm getting an empty foo tag. Did I copy something wrong?
Sean, the provided "XSLT code" causes compile time errors with any compliant XSLT 1.0 processor.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.