在 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),例如 &#8322;
时,CER 的 & 字符被转义为 &amp;
,因此选择菜单中显示的是 CER 而不是字符当菜单输出到页面显示时。
我尝试了以下两种方法: optionNode.appendChild(xmlDoc.createTextNode(label)); 和
optionNode.textContent = label;
两者都给出相同的结果。在将 XML 文档输出为文本后,我可以通过将 &amp;
全局替换为 &
来解决此问题:
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 输出包含 ₂ (例如),它在下拉菜单中显示为 ₂。如果 XML 输出包含 ,它也会显式显示。【参考方案2】:我找到了解决方案。在创建包含label
的节点之前,我将label
中的所有字符实体引用转换为Unicode 字符。然后,当我将 xml 作为字符串输出时,我将所有 Unicode 字符转换回字符实体引用。代码改编自我找到的代码elsewhere on Stack Overflow。
function cerToUnicode(str)
"use strict";
var entity_table =
'"': String.fromCharCode(34), // Quotation mark. Not required
'&': String.fromCharCode(38), // Ampersand
'<': String.fromCharCode(60), // Less-than sign
'>': String.fromCharCode(62), // Greater-than sign
' ': String.fromCharCode(160), // Non-breaking space
'¡': String.fromCharCode(161), // Inverted exclamation mark
... // other named CERs
;
str = str.replace(/&#(\d+);/g,
function (matched, capture1)
return (capture1 == '38' ? '&' : 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 中创建文本节点时避免转义字符实体引用的主要内容,如果未能解决你的问题,请参考以下文章
当字符串包含html实体时,在Javascript中设置文本节点的nodeValue