遇到一個問題,用LogParser擷取系統事件寫成XML檔,要分析XML時,卻因為ASP.NET 2.0傳回了一個XML內容含有不合法字元的錯誤事件而導致XmlDocument.Load()發生錯誤。

ASP.NET 2.0的錯誤是:
Exception type: XmlException
Exception message: '', hexadecimal value 0x08, is an invalid character. Line 11, position 12.

很妙的是,上面那個單引號所夾的,就是一個0x08 ASCII字元,而這個錯誤訊息被原原本本放到LogParser所產生的XML文件<Message>...</Message>Node中。導致的分析程式用XmlDocument.Load要載入LogParser產出的XML時,讀到ASCII 08,發生一模一樣的錯誤。

這有點像學生跟老師告狀:
"老師,王大明剛才踢人家屁股!"
"他怎麼踢你?"
"老師你先轉過去... 就像這樣..." (啪!!)

我找到一份討論串,提到XML中被視為不合法的字元包含了0x01-0x19(不含0x0a, 0x0d),所以我寫了以下的try ... catch,在解析錯誤時,試著將不合法字元移除後重試,在我遇到的案例中,這一招管用。

這又是一個足以展現Regular Expression威力的好例子(有些人應該會用迴圈跑30次Replace解這個問題吧!),還不太會用RegEx的人請看這裡

//分析結果
XmlDocument xd = new XmlDocument();
try
{
    xd.Load(file);
}
catch (System.Xml.XmlException xe)
{
    //將整個檔案讀成字串
    string rawXml = 
        System.IO.File.ReadAllText(file);
    string invalidCharsMatch = 
        "(?ims)[\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xb\xc\xe\xf" +
        "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19]";
 
    //取代其中無效字元, 通通換成空字串
   rawXml = System.Text.RegularExpressions.Regex.Replace(
        rawXml,
        invalidCharsMatch, "");
 
   xd.LoadXml(rawXml);
}

Comments

# by laneser

我的 code 如下: public class XmlTextConvert { // XML The the spec states: // Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] protected static Regex InvalidXMLCharacter = new Regex(@"[\u0000-\u0008|\u000B|\u000C|\u000E-\u001F|\uD800-\uDFFF|\uFFFE|\uFFFF]", RegexOptions.Compiled); public static string XmlConvertStr(string src) { return InvalidXMLCharacter.Replace(src, " "); } }

# by Jeffrey

To Laneser, 領教了!!! 您的寫法更精簡,又學到一記絕技,感謝!!

# by rosbicn

Laneser写的代码很精简,只是有个小错误。在正则表达式里面把竖线符号包含进去了,这样非法字符是去掉了,但是合法的竖线(|)也给去掉了。但愿Jeffrey没有把这个代码直接放到自己的程序里面,那样会引起连锁性的竖线症状。

# by finalevil

最近在處理讀取rss的問題,google到你的文章,很有幫助:)~謝啦

# by laneser

Thanks rosbicn ! 經過測試, 只要把 Regex 內容改為 [\u0000-\u0008\u000B\u000C\u000E-\u001F\uD800-\uDFFF\uFFFE\uFFFF] 就解決了該 bug. 謝謝提醒!

# by Will 保哥

把 Pattern 改成 \W+ 就可以了,更短一點 ^^

# by 阿翔

因為 &#x1E; 等非法字元也會造成xml無法正常運行 不知道是不是能將這些字串也去除掉呢? 我寫到 [\^&#x;$] 這就不知道怎麼寫了 拜託大家了

# by Jeffrey

to 阿翔, 可以給一個簡單的內含&#1E;會導致XML錯誤的實例嗎?

# by 阿翔

不好意思現在才看到 如下範例,我利用MS SQL 中的 for xml path('row')轉岀的XML字串,它會將XML非法字元轉成 &#x1E;等內容 . 我在extjs grid內利用XmlReader解析,會無法正常運作. 所以才在想是否能利用正規表示法,將這篇文章所說到的非法字元全部取代,在此謝謝大家Q_Q~ <row> <cas_no>1 </cas_no> <cas_title>光日段399&#x1E;</cas_title> </row> <row> <cas_no>2 </cas_no> <cas_title>台灣產業文化 </row>

# by Jeffrey

to 阿翔, 使用"&#[01][0-9A-F];"進行Regular Expression比對應可抓出 &#00; 到 &#1F; 共32個字元,將其置換成空字串,應能解決你的問題。

# by 阿翔

謝謝您~我再用看看^^~ 感恩~

# by Kin

如要把xml里的"去掉, 那要怎麽办?

# by Jeffrey

to Kin, 看不太明白,可否舉個具體範例嗎?

Post a comment