XSLT special characters
Asked Answered
D

5

8

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>
Demarco answered 28/5, 2010 at 0:53 Comment(1)
Good question (+1). See my answer for a complete solution.Kidney
K
10

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>
Kidney answered 28/5, 2010 at 1:28 Comment(0)
I
5

This is a really old question, and the other commenters are probably right to question why you need this, but if you just want to know how to add a < or > into your output here's how you do it.

<xsl:value-of disable-output-escaping="yes" select="string('&lt;')"/>

More info at the MSDN site.

Irrelevant answered 20/5, 2016 at 19:59 Comment(1)
man, i was searching for this for so long!Broadcloth
N
2

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.

Nourish answered 28/5, 2010 at 19:12 Comment(0)
M
0

Be careful if you're trying to escape anything besides an ampersand within a string literal. For example,

test="$some_variable = 'Wendy&apos;s'"

would not work. You have to escape that first ampersand in the escape string, so you'd need to use

test="$some_variable = 'Wendy&amp;apos;s'
Metaphase answered 16/12, 2015 at 20:42 Comment(0)
B
0

There should be no doubt if someone needs the output of brackets. I used XSLT to generate plain text and was pretty sure to what I need to output but the XslCompiledTransform class just encodes it for whatever reason.

As an shorter alternative to the answer of GMK I came up with:

<xsl:text disable-output-escaping="yes">&lt; ... &gt;</xsl:text>

see MSDN site

example in context:

<xsl:template match="data">
        /// <xsl:text disable-output-escaping="yes">&lt;summary&gt;</xsl:text>
        ///     <xsl:value-of select="value"/>
        /// <xsl:text disable-output-escaping="yes">&lt;/summary&gt;</xsl:text>
        public static <xsl:text disable-output-escaping="yes">Func&lt;string&gt; </xsl:text><xsl:value-of select="@name"/>
        <xsl:text disable-output-escaping="yes"> =&gt; () =&gt;</xsl:text> I18n.<xsl:value-of select="@name"/>;
</xsl:template>

This part generates something like this for C# resource files.

        /// <summary>
        ///     Abbrechen
        /// </summary>
        public static Func<string> Abort => () => I18n.Abort;
Brimstone answered 5/7, 2021 at 11:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.