Избегая экранирования ссылок на символьные сущности при создании текстового узла в XML
Я использую методы 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, '&');
но я уверен, что должен быть способ избежать побега. Любой совет?
2 ответа
Вы могли бы использовать 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>
Я нашел решение. Прежде чем создать узел, содержащий label
Я конвертирую все ссылки на сущности персонажа в label
Unicode символов. Затем при выводе xml в виде строки я преобразую все символы Unicode обратно в ссылки на объекты символов. Код адаптирован из кода, который я нашел в другом месте в переполнении стека.
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()