tags:

views:

69

answers:

3

I have an XML file which has many section like the one below:

<Operations>
  <Action [some attributes ...]>
    [some complex content ...]
  </Action>
  <Action [some attributes ...]>
    [some complex content ...]
  </Action>
</Operations>

I have to add an <Action/> to every <Operations/>. It seems that an XSLT should be a good solution to this problem:

<xsl:template match="Operations/Action[last()]">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
  <Action>[some complex content ...]</Action>
</xsl:template>

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

My problem is that the content of my <Action/> contains some xPath expressions. For example:

<Action code="p_histo01">
  <customScript languageCode="gel">
    <gel:script
          xmlns:core="jelly:core"
          xmlns:gel="jelly:com.niku.union.gel.GELTagLibrary"
          xmlns:soap="jelly:com.niku.union.gel.SOAPTagLibrary"
          xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
          xmlns:sql="jelly:sql"
          xmlns:x="jelly:xml"
          xmlns:xog="http://www.niku.com/xog"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
      <sql:param value="${gel_stepInstanceId}"/>
    </gel:script>
  </customScript>
</Action>

The ${gel_stepInstanceId} is interpreted by my XSLT but I would like it to be copied as-is. Is that possible? How?

A: 

Sure, that's easy enough:

<sql:param value="{'${gel_stepInstanceId}'}"/>

The curly braces are "attribute value template" (AVT) syntax. There is no string escaping defined in XSLT, so you have to work around that - easiest by defining an actual AVT and and passing it a string value to display.

Tomalak
Thanks for the suggestion, but replacing 100's of ${} is a bit too much work. See my solution below.
Guillaume
Tomalak, XSLT simply allows you to double the curly braces to output an attribute value with one curly brace e.g. `<sql:param value="${{gel_stepInstanceId}}"/>` so I am not sure why you say you need a workaround with a string. Or are you just prefering the string approach to doubling the curly braces?
Martin Honnen
@Martin: I was simply unaware of that fact.
Tomalak
@Tomalak, Just follow the link in my answer.
Dimitre Novatchev
@Dimitre: Obviously there's always something new to learn. :) Will remember this from now on.
Tomalak
A: 

I found that I can use :

<xsl:text disable-output-escaping="yes">
  <[CDATA[
    <Action>[...]</Action>
  ]]>
</xsl:text>

It is easier for me than to replace all instances of ${} ...

This solution works for me by running my XSLT with XMLSpy, but the documentation I found let me think that "disable-output-escaping" is deprecated ... Use at your own risk ...

Guillaume
That's also one way to do it.
Tomalak
Good Question (+1). See my answer for the most precise and easy way to achieve this. :)
Dimitre Novatchev
+1  A: 

The XSLT 1.0 (and also 2.0) spec defines a strict way to escape curly braces inside an attribute value, so that they are not use to denote the start/end of an AVT.

To quote from the spec:

When an attribute value template is instantiated, a double left or right curly brace outside an expression will be replaced by a single curly brace.

Use:

  <sql:param value="${{gel_stepInstanceId}}"/>
Dimitre Novatchev