tags:

views:

37

answers:

3

In the following XSL transformation how do I output the '<' and '>' symbol?

Input XML:

<TestResult bugnumber="3214" testname="display.methods::close->test_ManyInvoke" errortype="Failure"><ErrorMessage><![CDATA[calling close() method failed - expected:<2>]]></ErrorMessage>

XSLT:

<xsl:template match="TestResult">
  <xsl:variable name="errorMessage">
   <xsl:value-of select="ErrorMessage" disable-output-escaping="yes"/>
  </xsl:variable>
  <Test name='{@testname}'>
   <TestResult>
    <Passed>false</Passed>
    <State>failure</State>
    <Metadata>
     <Entry name='bugnumber' value='{@bugnumber}' />
    </Metadata>
    <TestOutput>
     <Metadata>
      <Entry name='ErrorMessage' value='{$errorMessage}' />
     </Metadata>
    </TestOutput>
   </TestResult>
  </Test>
 </xsl:template>

Output XML:

<Test name="display.methods::close-&gttest_ManyInvoke"> 
 <TestResult>
  <Passed>false</Passed>
  <State>failure</State>
  <Metadata>
   <Entry name="bugnumber" value="3214"/>
  </Metadata>
  <TestOutput>
   <Metadata>
    <Entry name="ErrorMessage" value="calling close() method failed - expected:&lt;2&gt;"/>
   </Metadata>
  </TestOutput>
 </TestResult>
</Test>
A: 

Without delving into trial and error over here: http://www.dpawson.co.uk/xsl/sect2/cdata.html looks like it could contain your answer...

Reddog
+3  A: 

Short answer: You can't.

Long answer: The value of attributes cannot contain a few special characters, such as '<', '>' and '&'.

If present, they are escaped as: '&lt;', '&gt;' and '&amp;' .

These characters can be produced if the output method is 'text', which is not your case.

Text that looks like these characters when displayed in a browser can also be produced: use: '&lt;', '&gt;' and '&amp;'.

Finally, you can produce these characters as part of a text node using CDATA section. The following example illustrates this:

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

 <xsl:template match="/">
  <t> &lt; &amp; &gt;</t>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on any XML document (not used), the result is:

<t><![CDATA[ < & >]]></t>
Dimitre Novatchev
+1  A: 

If the fact that &gt; is showing up in your attributes is a problem, the problem is with how the XML is being consumed, not how it's being produced.

Any XML parser will unescape escaped character entities when it's used to retrieve an attribute value. If you use an XML parser in the consumption of an XML document, you'll never see this; the parser will tell you that the value of the attribute is display.methods::close->test_ManyInvoke.

It seems likely to me that this "problem" is only appearing for one of two reasons:

  1. Someone who doesn't understand how XML works is looking at the output and saying, "Hey, it shouldn't be doing that."

  2. Someone who doesn't understand how XML works has written his own logic to parse XML. ("Why should I use somebody else's XML parser when I can just write a simple regular expression?" Well, this is one reason why.)

As a general rule of thumb, if you ever find yourself using disable-output-escaping='yes' in XSLT, or creating CDATA sections, you're probably doing the wrong thing. It's not certain - there are appropriate uses for both - but in my experience, the vast majority of time if the answer is "use CDATA" you're asking the wrong question.

Robert Rossney