在JavaScript(服务器端nodejs)中,我正在编写一个生成xml作为输出的程序。
我通过连接字符串来构建xml:
str += '<' + key + '>';
str += value;
str += '</' + key + '>';
问题是:如果value包含'&','>'或字符,该'<'怎么办?逃脱这些角色的最佳方法是什么?
还是周围有可以逃避XML实体的JavaScript库?
Answers:
HTML编码简单地更换&,",',<和>与他们的实体当量字符。顺序很重要,如果您不先替换&字符,则会对某些实体进行双重编码:
if (!String.prototype.encodeHTML) {
String.prototype.encodeHTML = function () {
return this.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
};
}
正如@Johan BW de Vries指出的那样,这将与标签名称有关,我想澄清一下,我假设这仅用于value
相反,如果要解码HTML实体1,请确保在其他所有内容之后都解码&为&,以免对任何实体进行双重解码:
if (!String.prototype.decodeHTML) {
String.prototype.decodeHTML = function () {
return this.replace(/'/g, "'")
.replace(/"/g, '"')
.replace(/>/g, '>')
.replace(/</g, '<')
.replace(/&/g, '&');
};
}
1只是基础知识,不包括©to©或其他此类事物
就图书馆而言。Underscore.js(或Lodash如果你愿意)提供了一个_.escape执行此功能的方法。
.replace()。无论哪种情况,您都必须拥有大量数据才能注意到任何重大问题。一种更快的替代方法是对您的应用进行基准测试并找到实际的阻塞点(通常是嵌套循环),而不用担心像这样微不足道的事情。
同样的结果可能会更有效:
function escapeXml(unsafe) {
return unsafe.replace(/[<>&'"]/g, function (c) {
switch (c) {
case '<': return '<';
case '>': return '>';
case '&': return '&';
case '\'': return ''';
case '"': return '"';
}
});
}
如果您使用jQuery,这是一个简单的解决方案:
String.prototype.htmlEscape = function() {
return $('<div/>').text(this.toString()).html();
};
像这样使用它:
"<foo&bar>".htmlEscape(); -> "<foo&bar>"
$('<div/>').text('<&\'>"').html() -> "<&'>""
您可以使用以下方法。我已经在原型中添加了它,以便于访问。如果调用两次或两次以上,我也使用负前瞻,因此它不会弄乱事情。
用法:
var original = "Hi&there";
var escaped = original.EncodeXMLEscapeChars(); //Hi&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, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
OutPut = OutPut.replace(/&(?!(amp;)|(lt;)|(gt;)|(quot;)|(#39;)|(apos;))/g, "&");
OutPut = OutPut.replace(/([^\\])((\\\\)*)\\(?![\\/{])/g, "$1\\\\$2"); //replaces odd backslash(\\) with even.
}
else {
OutPut = "";
}
return OutPut;
};
let a = 'foo'将受到此代码的影响。更好地创建辅助函数,而不是扩展原型。
我最初在生产代码中使用了可接受的答案,但发现大量使用它实际上确实很慢。这里是一个很大更快的解决方案(运行超过两倍的速度):
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("<>&")); //<>&
document对象。我没有
注意,如果在XML中包含XML,则所有的正则表达式都不好。
而是将字符串循环一次,并替换所有转义字符。
这样一来,您就无法两次超过同一个角色。
function _xmlAttributeEscape(inputString)
{
var output = [];
for (var i = 0; i < inputString.length; ++i)
{
switch (inputString[i])
{
case '&':
output.push("&");
break;
case '"':
output.push(""");
break;
case "<":
output.push("<");
break;
case ">":
output.push(">");
break;
default:
output.push(inputString[i]);
}
}
return output.join("");
}
从技术上讲,&,<和>不是有效的XML实体名称字符。如果您不信任键变量,则应将其过滤掉。
如果希望它们作为HTML实体转义,则可以使用类似http://www.strictly-software.com/htmlencode的名称。
如果以前有东西逃脱,您可以尝试一下,因为这不会像其他许多东西一样使逃脱
function escape(text) {
return String(text).replace(/(['"<>&'])(\w+;)?/g, (match, char, escaped) => {
if(escaped)
return match
switch(char) {
case '\'': return '"'
case '"': return '''
case '<': return '<'
case '>': return '>'
case '&': return '&'
}
})
}
这很简单:
sText = ("" + sText).split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'");