как избежать сущностей XML в JavaScript? - PullRequest
67 голосов
/ 27 октября 2011

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

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

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

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

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

Ответы [ 8 ]

98 голосов
/ 27 октября 2011
Кодировка

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;');
  };
}

As @Johan B.W. де Врис указал, что это будет иметь проблемы с именами тегов, я хотел бы уточнить, что я сделал предположение, что это используется только для 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; до © или другие подобные вещи


Что касается библиотек. Underscore.js (или Lodash , если вы предпочитаете) предоставляет метод _.escape для выполнения этой функции.

90 голосов
/ 16 января 2015

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

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;';
        }
    });
}
19 голосов
/ 23 февраля 2012

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

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

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

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

6 голосов
/ 22 сентября 2015

вы можете использовать метод ниже.Я добавил это в прототип для облегчения доступа.Я также использовал отрицательный прогноз, чтобы не мешать, если вы вызываете этот метод дважды или более.в 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, "$1\\\\$2");  //replaces odd backslash(\\) with even.
    }
    else {
        OutPut = "";
    }
    return OutPut;
};
1 голос
/ 11 мая 2018

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

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

ссылка

1 голос
/ 09 ноября 2017

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

   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;
0 голосов
/ 01 февраля 2016

Это просто:

sText = ("" + sText).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;");
0 голосов
/ 27 октября 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...