как избежать XML-объектов в javascript?


в JavaScript (на стороне сервера nodejs) я пишу программу, которая генерирует xml в качестве вывода.

Я строю xml путем объединения строки:

str += '<' + key + '>';
str += value;
str += '</' + key + '>';

проблема в том, что если value содержит символы, такие как '&','>' или '<'? Каков лучший способ избежать этих персонажей?

или есть ли библиотека javascript, вокруг которой можно избежать XML-объектов?

8 55

8 ответов:

HTML кодировка просто заменяет &,",',< и > символы с их эквивалентами сущностей. Порядок имеет значение, если вы не замените & символы во-первых, вы будете дважды кодировать некоторые из объектов:

if (!String.prototype.encodeHTML) {
  String.prototype.encodeHTML = function () {
    return this.replace(/&/g, '&amp;')
               .replace(/</g, '&lt;')
               .replace(/>/g, '&gt;')
               .replace(/"/g, '&quot;')
               .replace(/'/g, '&apos;');
  };
}

как отметил @Johan B. W. de Vries, у этого будут проблемы с именами тегов, я хотел бы уточнить, что я сделал предположение, что это используется для value только

наоборот, если вы хотите декодировать HTML-объекты1, убедитесь, что вы расшифруйте &amp; до & после всего остального, так что вы не дважды декодировать любые объекты:

if (!String.prototype.decodeHTML) {
  String.prototype.decodeHTML = function () {
    return this.replace(/&apos;/g, "'")
               .replace(/&quot;/g, '"')
               .replace(/&gt;/g, '>')
               .replace(/&lt;/g, '<')
               .replace(/&amp;/g, '&');
  };
}

1 только основы, не включая &copy; до © или другие подобные вещи


что касается библиотек. подчеркивания.js (или Лодашь если вы предпочитаете) обеспечивает _.escape способ для выполнения этой функции.

Это может быть немного более эффективным с тем же результатом:

function escapeXml(unsafe) {
    return unsafe.replace(/[<>&'"]/g, function (c) {
        switch (c) {
            case '<': return '&lt;';
            case '>': return '&gt;';
            case '&': return '&amp;';
            case '\'': return '&apos;';
            case '"': return '&quot;';
        }
    });
}

Если у вас есть jQuery, вот простое решение:

  String.prototype.htmlEscape = function() {
    return $('<div/>').text(this.toString()).html();
  };

используйте его так:

"<foo&bar>".htmlEscape(); ->"&lt;foo&amp;bar&gt"

вы можете использовать следующий метод. Я добавил Это в прототип для более легкого доступа. Я также использовал отрицательный взгляд вперед, поэтому он не испортит вещи, если вы вызовете метод дважды или более.

использование:

 var original = "Hi&there";
 var escaped = original.EncodeXMLEscapeChars();  //Hi&amp;there

декодирование автоматически обрабатывается в XML-парсере.

способ :

//String Extenstion to format string for xml content.
//Replces xml escape chracters to their equivalent html notation.
String.prototype.EncodeXMLEscapeChars = function () {
    var OutPut = this;
    if ($.trim(OutPut) != "") {
        OutPut = OutPut.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
        OutPut = OutPut.replace(/&(?!(amp;)|(lt;)|(gt;)|(quot;)|(#39;)|(apos;))/g, "&amp;");
        OutPut = OutPut.replace(/([^\])((\\)*)\(?![\/{])/g, "\\");  //replaces odd backslash(\) with even.
    }
    else {
        OutPut = "";
    }
    return OutPut;
};

Я первоначально использовал принятый ответ в производственном коде и обнаружил, что он был на самом деле очень медленным при интенсивном использовании. Вот это много более быстрое решение (работает более чем в два раза быстрее):

   var escapeXml = (function() {
        var doc = document.implementation.createDocument("", "", null)
        var el = doc.createElement("temp");
        el.textContent = "temp";
        el = el.firstChild;
        var ser =  new XMLSerializer();
        return function(text) {
            el.nodeValue = text;
            return ser.serializeToString(el);
        };
    })();

console.log(escapeXml("<>&")); //&lt;&gt;&amp;

может быть, вы можете попробовать это,

function encodeXML(s) {
  const dom = document.createElement('div')
  dom.textContent = s
  return dom.innerHTML
}

ссылка

технически,&, не являются допустимыми символами имени сущности XML. Если вы не можете доверять ключевой переменной, вы должны фильтровать их.

Если вы хотите, чтобы они экранировались как HTML-объекты, вы можете использовать что-то вроде http://www.strictly-software.com/htmlencode .

Это просто:

sText = ("" + sText).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;");