簡體   English   中英

如何在javascript中轉義xml實體?

[英]how to escape xml entities in javascript?

在 JavaScript(服務器端 nodejs)中,我正在編寫一個生成 xml 作為輸出的程序。

我通過連接一個字符串來構建 xml:

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

問題是:如果value包含像'&''>''<'這樣的字符怎么辦? 逃脫這些角色的最佳方法是什么?

或者是否有任何可以轉義 XML 實體的 javascript 庫?

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 BW 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; ©或其他類似的事情


就圖書館而言。 Underscore.js (或者Lodash ,如果你喜歡的話)提供了一個_.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, "$1\\\\$2");  //replaces odd backslash(\\) with even.
    }
    else {
        OutPut = "";
    }
    return OutPut;
};

注意,如果 XML 中包含 XML,那么所有的正則表達式都不好。
而是在字符串上循環一次,並替換所有轉義字符。
這樣一來,你就不能兩次碾過同一個角色。

function _xmlAttributeEscape(inputString)
{
    var output = [];

    for (var i = 0; i < inputString.length; ++i)
    {
        switch (inputString[i])
        {
            case '&':
                output.push("&amp;");
                break;
            case '"':
                output.push("&quot;");
                break;
            case "<":
                output.push("&lt;");
                break;
            case ">":
                output.push("&gt;");
                break;
            default:
                output.push(inputString[i]);
        }


    }

    return output.join("");
}

我最初在生產代碼中使用了公認的答案,發現在大量使用時它實際上真的很慢。 這是一個更快的解決方案(以兩倍以上的速度運行):

   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
}

參考

如果之前有什么東西被轉義了,你可以試試這個,因為這不會像許多其他人一樣雙重轉義

function escape(text) {
    return String(text).replace(/(['"<>&'])(\w+;)?/g, (match, char, escaped) => {
        if(escaped) 
            return match

        switch(char) {
            case '\'': return '&quot;'
            case '"': return '&apos;'
            case '<': return '&lt;'
            case '>': return '&gt;'
            case '&': return '&amp;'
        }
    })
}

加上 ZZZZBov 的答案,我發現這更清晰,更易於閱讀:

const encodeXML = (str) =>
    str
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&apos;');

此外,所有五個字符都可以在此處找到,例如: https ://www.sitemaps.org/protocol.html

請注意,這僅對值進行編碼(如其他人所述)。

既然我們有字符串插值和其他一些現代化,現在是時候進行更新了。 並使用對象查找,因為它確實應該。

const escapeXml = (unsafe) =>
    unsafe.replace(/[<>&'"]/g, (c) => `&${({
        '<': 'lt',
        '>': 'gt',
        '&': 'amp',
        '\'': 'apos',
        '"': 'quot'
    })[c]};`);

從技術上講,&、< 和 > 不是有效的 XML 實體名稱字符。 如果您不能信任關鍵變量,則應將其過濾掉。

如果您希望它們作為 HTML 實體轉義,您可以使用類似http://www.strictly-software.com/htmlencode的內容。

這很簡單:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM