9

I'm having a problem with the Dom class and its automatic escaping of strings added via Dom.XmlNode.addTextNode(text) and I'm not sure if I am doing it wrong and this is expected behavior or if this is a bug in the method.

Given a string: Escaping special characters: < " ' > & these should all be escaped

What I expected to happen was no automatic escaping of text by the Dom class, creating text nodes with unescaped entities and to need to use the String.escapeXml() method to sanitize the string myself.

However, due to the automatic escaping that is happening in the .addTextNode() method (or maybe in .toXmlString()), the result is double-escaped entities. (i.e. &amp;amp;)

My understanding is that there are 5 entities that should be escaped in XML. < " ' > &
Source: List of XML and HTML character entity references

Unfortunately, based on my testing it looks like the .addTextNode() method only escapes < and &. So, I cannot rely on the method to escape the proper characters on my behalf, and I cannot pre-escape the string as it will result in double-escaped entities.

Exec Anon:

String bookTitle = 'XML Escaping';
String bookSubject = 'Escaping special characters: < " \' > & these should all be escaped';
system.debug('Subject: ' + bookSubject);

// create the Document
Dom.Document xmlDoc = new Dom.Document();

// create the root node & one child node with two child nodes containing text
dom.XmlNode DocumentRoot = xmlDoc.createRootElement('DocumentRoot', 'someNS', '');
  dom.XmlNode BookInfo = DocumentRoot.addChildElement('BookInfo', null, null);
    BookInfo.addChildElement('Title', null, null).addTextNode(bookTitle);
    BookInfo.addChildElement('Subject', null, null).addTextNode(bookSubject);


// output the results
String xmlAsString = xmlDoc.toXmlString();
system.debug('&gt; : ' + xmlAsString.contains('&gt;'));
system.debug('&lt; : ' + xmlAsString.contains('&lt;'));
system.debug('&amp; : ' + xmlAsString.contains('&amp;'));
system.debug('&quot; : ' + xmlAsString.contains('&quot;'));
system.debug('&apos; : ' + xmlAsString.contains('&apos;'));

// for good measure
system.debug(xmlAsString);

Results:

Subject: Escaping special characters: < " ' > & these should all be escaped

&gt; : false
&lt; : true
&amp; : true
&quot; : false
&apos; : false

<?xml version="1.0" encoding="UTF-8"?>
<DocumentRoot xmlns="someNS">
    <BookInfo>
        <Title>XML Escaping</Title>
        <Subject>Escaping special characters: &lt; " ' > &amp; these should all be escaped</Subject>
    </BookInfo>
</DocumentRoot>
  1. Is this a bug?
  2. Am I building a node containing text that may contain unsafe characters incorrectly?
  3. Is there an alternative using the Dom classes?
    (I don't desire to build the XML output via strings by hand.)

Update:

In the end, this wasn't a problem with the entities in the XML structure but was actually a problem that stemmed from forgetting to UTF-8 encode the raw XML string when it was used in a application/x-www-form-urlencoded payload and sent out as an HTTPRequest. Don't forget your encoding!

EncodingUtil.urlEncode(xmlAsString, 'UTF-8');

1 Answer 1

5
+100

In element text the only requirement is to escape < and &, so i beleive the behaviour you're seeing is correct.

The Character data section of the XML Spec says

"The ampersand character (&) and the left angle bracket (<) must not appear in their literal form, except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section. If they are needed elsewhere, they must be escaped using either numeric character references or the strings "&amp;" and "&lt;" respectively."

It goes on to explain the escaping > is optional, except for the end of a CDATA section, which is a sequence of ]]> if you add this to your test you can see that that is correctly escaped to ]]&gt; so everything appears to be behaving correctly.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .