在XML中创建文本节点时避免转义字符实体引用

时间:2018-03-21 19:42:38

标签: xml escaping createtextnode

我正在使用XML DOM技术在JavaScript中构建下拉菜单。创建<option>节点后,我附加了应该为该选项显示的文本。我面临的问题是,当文本包含字符实体引用(CER)时,例如&#8322;&amp; CER的字符被转义为&amp;,因此当菜单输出到页面进行显示时,CER而不是字符会显示在选择菜单中。我尝试了以下两种方法:

optionNode.appendChild(xmlDoc.createTextNode(label));

optionNode.textContent = label;

并且都给出相同的结果。在将XML文档输出到文本后,我可以通过使用&amp;全局替换&来解决此问题:

var xml = (new XMLSerializer()).serializeToString(xmlDoc);
return xml.replace(/&amp;/g, '&');

但我确信必须有办法避免首先逃避。有什么建议吗?

2 个答案:

答案 0 :(得分:0)

您可以使用createCDATASection()代替createTextNode()

var docu = new DOMParser().parseFromString('<xml></xml>',  "application/xml")
var cdata = docu.createCDATASection('Some <CDATA> data & then some');
docu.getElementsByTagName('xml')[0].appendChild(cdata);

alert(new XMLSerializer().serializeToString(docu));
// Displays: <xml><![CDATA[Some <CDATA> data & then some]]></xml>

答案 1 :(得分:0)

我找到了解决方案。在创建包含label的节点之前,我将label中的所有字符实体引用转换为Unicode字符。然后,当我将xml作为String输出时,我将所有Unicode字符转换回字符实体引用。代码改编自我发现elsewhere on Stack Overflow的代码。

function cerToUnicode(str) {
    "use strict";
    var entity_table = {
       '&quot;': String.fromCharCode(34), // Quotation mark. Not required
       '&amp;': String.fromCharCode(38), // Ampersand
               '&lt;': String.fromCharCode(60), // Less-than sign
       '&gt;': String.fromCharCode(62), // Greater-than sign
       '&nbsp;': String.fromCharCode(160), // Non-breaking space
       '&iexcl;': String.fromCharCode(161), // Inverted exclamation mark
       ... // other named CERs
   };
   str = str.replace(/&#(\d+);/g,
       function (matched, capture1) {
           return (capture1 == '38' ? '&amp;' : String.fromCharCode(capture1));
       });
   str = str.replace(/&[^;]*;/g,
       function (matched) {
           return entity_table[matched];
       });
   return str;
} // cerToUnicode()

function unicodeToCER(str) {
    return str.replace(/./gm, function(s) {
        var code = s.charCodeAt(0);
        return (code < 128 ? s : "&#" + code + ";");
    });
} // unicodeToCER()