XML Attribute的特殊字元處理DIY
我有段程式為了貪圖效能,沒用XmlDocument,而用StringBuilder自己組XML:
sb.AppendFormat("<Event Log=\"{0}\" Message=\"{1}\" />\n",
logName,System.Web.HttpUtility.HtmlEncode(e.Message));
結果,今天突然程式發生Error,才發現這段程式乍看OK,嚴謹性卻大有問題。原因出在e.Message中可能包含一些HtmlEncode認定合法,但XML不接受的特殊字元(例如: 換行、\t之類的),組出來的XML是不合法的。
於是,我寫了以下的Code做測試(用了一個ASCII 01(笑臉)跟\n(換行)當成非法)
static void Lab0802()
{
XmlDocument xd = new XmlDocument();
xd.LoadXml("<ROOT></ROOT>");
XmlElement xe = xd.CreateElement("X");
XmlAttribute xa = xd.CreateAttribute("N");
xa.Value = "<ab>\x1\n</ab>";
xe.Attributes.Append(xa);
xd.DocumentElement.AppendChild(xe);
Console.WriteLine(xd.OuterXml);
Console.WriteLine(System.Web.HttpUtility.HtmlAttributeEncode(xa.Value));
}
使用XML DOM的結果,合法的XML應為<ROOT><X N="<ab>
</ab>" /></ROOT>,而使用HtmlEncode的結果,\n與\x1都沒被置換。當Attribute中出現這些非法字元,在XmlDocument.LoadXml時,就會發生Error!
找了半天,沒找到現成的函數可以處理這個問題(有個XmlConvert.EncodeName()可處理Attribute名稱的特殊字元(例如: 中文),但其規則與Attribute Value的Encode不同,所以無法借用),只好自己DIY寫了這個函數,有類似需求的人可以引用,發現邏輯有錯的話請通知我修改。
//當字串中可能包含特別的ASCII碼時,做額外的轉換
public static string XmlAttributeEncode(string raw)
{
string s = System.Web.HttpUtility.HtmlEncode(raw);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
//要處理的範圍
if ((c>=0 && c < 32) || (c > 127 && c<=255))
sb.AppendFormat("&#x{0:x};", (byte) c);
else
sb.Append(c);
}
return sb.ToString();
}
sb.AppendFormat("<Event Log=\"{0}\" Message=\"{1}\" />\n",
logName,System.Web.HttpUtility.HtmlEncode(e.Message));
結果,今天突然程式發生Error,才發現這段程式乍看OK,嚴謹性卻大有問題。原因出在e.Message中可能包含一些HtmlEncode認定合法,但XML不接受的特殊字元(例如: 換行、\t之類的),組出來的XML是不合法的。
於是,我寫了以下的Code做測試(用了一個ASCII 01(笑臉)跟\n(換行)當成非法)
static void Lab0802()
{
XmlDocument xd = new XmlDocument();
xd.LoadXml("<ROOT></ROOT>");
XmlElement xe = xd.CreateElement("X");
XmlAttribute xa = xd.CreateAttribute("N");
xa.Value = "<ab>\x1\n</ab>";
xe.Attributes.Append(xa);
xd.DocumentElement.AppendChild(xe);
Console.WriteLine(xd.OuterXml);
Console.WriteLine(System.Web.HttpUtility.HtmlAttributeEncode(xa.Value));
}
使用XML DOM的結果,合法的XML應為<ROOT><X N="<ab>
</ab>" /></ROOT>,而使用HtmlEncode的結果,\n與\x1都沒被置換。當Attribute中出現這些非法字元,在XmlDocument.LoadXml時,就會發生Error!
找了半天,沒找到現成的函數可以處理這個問題(有個XmlConvert.EncodeName()可處理Attribute名稱的特殊字元(例如: 中文),但其規則與Attribute Value的Encode不同,所以無法借用),只好自己DIY寫了這個函數,有類似需求的人可以引用,發現邏輯有錯的話請通知我修改。
//當字串中可能包含特別的ASCII碼時,做額外的轉換
public static string XmlAttributeEncode(string raw)
{
string s = System.Web.HttpUtility.HtmlEncode(raw);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
//要處理的範圍
if ((c>=0 && c < 32) || (c > 127 && c<=255))
sb.AppendFormat("&#x{0:x};", (byte) c);
else
sb.Append(c);
}
return sb.ToString();
}
0 Comments:
Post a Comment
<< Home