在JavaScript(服务器端nodejs)中,我正在编写一个生成xml作为输出的程序。
我通过连接字符串来构建xml:
str += '<' + key + '>';
str += value;
str += '</' + key + '>';
问题是:如果value
包含'&'
,'>'
或'<'
等字符会怎样?
逃避这些角色的最佳方法是什么?
或者是否有任何javascript库可以绕过XML实体?
答案 0 :(得分:97)
HTML编码只是将&
,"
,'
,<
和>
字符替换为其实体等效字符。订单很重要,如果您不首先替换&
字符,您将对某些实体进行双重编码:
if (!String.prototype.encodeHTML) {
String.prototype.encodeHTML = function () {
return this.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
};
}
作为@Johan B.W. 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只是基础知识,不包括©
到©
或其他类似的事情
就图书馆而言。 Underscore.js(如果您愿意,可以Lodash)提供_.escape
方法来执行此功能。
答案 1 :(得分:87)
对于相同的结果,这可能会更有效:
function escapeXml(unsafe) {
return unsafe.replace(/[<>&'"]/g, function (c) {
switch (c) {
case '<': return '<';
case '>': return '>';
case '&': return '&';
case '\'': return ''';
case '"': return '"';
}
});
}
答案 2 :(得分:19)
如果你有jQuery,这是一个简单的解决方案:
String.prototype.htmlEscape = function() {
return $('<div/>').text(this.toString()).html();
};
像这样使用:
"<foo&bar>".htmlEscape();
- &gt; "<foo&bar>"
答案 3 :(得分:6)
您可以使用以下方法。我在原型中添加了这个以便于访问。 我也使用了负向前瞻,所以如果你把方法调用两次或更多,它就不会弄乱。
<强>用法:强>
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;
};
答案 4 :(得分:1)
我最初在生产代码中使用了已接受的答案,并发现在大量使用时它实际上非常慢。这是一个很多更快的解决方案(运行速度超过两倍):
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("<>&")); //<>&
答案 5 :(得分:1)
警告,如果您在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("");
}
答案 6 :(得分:0)
技术上,&amp;,&lt;和&gt;不是有效的XML实体名称字符。如果您不能信任密钥变量,则应将其过滤掉。
如果您希望将它们转义为HTML实体,则可以使用http://www.strictly-software.com/htmlencode。
之类的内容答案 7 :(得分:0)
如果从以前逃脱了一些东西,您可以尝试一下,因为这样不会像其他许多东西一样使逃脱
import csv
with open('nba.csv', newline='') as csvfile:
reader = csv.DictReader(csvfile)
data = []
for row in reader:
print(row['Name'], row['Salary'])
答案 8 :(得分:-1)
这很简单:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="#777777"
card_view:cardCornerRadius="0dp"
card_view:cardElevation="3dp"
card_view:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center_vertical|center_horizontal"
android:orientation="horizontal"
android:weightSum="10">
<LinearLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="3">
<ImageView
android:id="@+id/thumbImageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/soul_bg" />
</LinearLayout>
<LinearLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="7">
<TableLayout
android:id="@+id/tableLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:stretchColumns="0,1,2"
android:weightSum="6">
<TableRow
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="3"
android:textColor="#FFF"
android:weightSum="3">
<TextView
android:id="@+id/nameTextView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Name:"
android:textColor="#FFF" />
<TextView
android:id="@+id/hpTextView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="HP:"
android:textColor="#FFF" />
<TextView
android:id="@+id/atkTextView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="ATK:"
android:textColor="#FFF" />
</TableRow>
<TableRow
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="3"
android:textColor="#FFF"
android:weightSum="3">
<TextView
android:id="@+id/typeTextView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Race:"
android:textColor="#FFF" />
<TextView
android:id="@+id/defTextView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="DEF"
android:textColor="#FFF" />
<TextView
android:id="@+id/wisTextView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="WIS"
android:textColor="#FFF" />
</TableRow>
</TableLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>