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

Posted

技术标签:

【中文标题】在 XML 中创建文本节点时避免转义字符实体引用【英文标题】:Avoiding escaping character entity references when creating a text node in XML 【发布时间】:2018-08-31 02:23:39 【问题描述】:

我正在使用 XML DOM 技术在 javascript 中构建下拉菜单。

创建<option> 节点后,我会附加应该为该选项显示的文本。我面临的问题是,当文本包含字符实体引用 (CER),例如 ₂ 时,CER 的 & 字符被转义为 &,因此选择菜单中显示的是 CER 而不是字符当菜单输出到页面显示时。

我尝试了以下两种方法: optionNode.appendChild(xmlDoc.createTextNode(label)); 和

optionNode.textContent = label;

两者都给出相同的结果。在将 XML 文档输出为文本后,我可以通过将 & 全局替换为 & 来解决此问题:

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

但我敢肯定,首先必须有一种方法可以避免逃跑。有吗?

【问题讨论】:

【参考方案1】:

您可以使用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>

【讨论】:

也有同样的问题。 是的,我试过了,但是我的字符串输出包含 ,它出现在下拉菜单中,所以我要重新进行全局替换。 好吧,如果 CDATA 和实体有问题,听起来您不想要 XML 序列化。您如何阅读或应用输出?除非您不使用 XML api 进行读取,否则它应该被“读取”并毫无问题地解释。 正如我所说,我正在构建一个下拉菜单,其中显示给用户的选项可能包含字符实体引用。我将从 XMLSerializer 获得的字符串附加到更大的 html 字符串中,然后使用 innerHTML 将更大的字符串(包括下拉菜单)放在页面上。如果序列化程序的 XML 输出包含 &#8322; (例如),它在下拉菜单中显示为 ₂。如果 XML 输出包含 ,它也会显式显示。【参考方案2】:

我找到了解决方案。在创建包含label 的节点之前,我将label 中的所有字符实体引用转换为Unicode 字符。然后,当我将 xml 作为字符串输出时,我将所有 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()

【讨论】:

以上是关于在 XML 中创建文本节点时避免转义字符实体引用的主要内容,如果未能解决你的问题,请参考以下文章

(转)XML中必须进行转义的字符

当字符串包含html实体时,在Javascript中设置文本节点的nodeValue

[转]xml文件中的转义字符

为啥html,xml的特殊符号转义不用斜杠,而要用& quot ;这样的奇怪形式?

大文本字符串中的 CreateTextNode 转义字符

xml节点中的转义字符