最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c#中XML解析文件出錯解決方法

 更新時間:2014年08月17日 10:03:45   投稿:mdxy-dxy  
在解析xml時,經(jīng)常因為文件中含特殊字符而解析失敗。原因有兩個:一是內(nèi)容中含有XML預(yù)定義好的實體,二是內(nèi)容中含有低位非打印字符

1.內(nèi)容中含有xml預(yù)定好的實體,如“<”和“&”,對xml來說是禁止使用的,針對這種字符,解決方式是使用CDATA部件以"<![CDATA[" 標(biāo)記開始,以"]]>"標(biāo)記結(jié)束,是CDATA內(nèi)部內(nèi)容被解析器忽略。具體說明參考《XML CDATA是什么?》。

2.內(nèi)容中含有低位非打印字符,解析時會報錯:""(十六進(jìn)制值 0x1D)是無效的字符.加載或保存XML時引發(fā)的異常.System.ArgumentException: “”(十六進(jìn)制值 0x1D)是無效的字符。

出錯的原因是內(nèi)容中含有低位非打印字符,處理方法是對其進(jìn)行過濾,過濾方法為:

return System.Text.RegularExpressions.Regex.Replace(str,@"[\x00-\x08]|[\x0B-\x0C]|[\x0E-\x1F]";

以上兩種情況,第一種較為普遍,第二種遇到情況比較少,在面對一些用戶輸入數(shù)據(jù)時生成xml,可以對xml結(jié)點內(nèi)容執(zhí)行上述過濾,以保證xml文件使用者可以正確解析xml文檔。

以下是詳細(xì)解釋:

“”(十六進(jìn)制值 0x1D)是無效的字符

加載或保存XML時引發(fā)的異常.System.ArgumentException: “”(十六進(jìn)制值 0x1D)是無效的字符。
產(chǎn)生原因是xml文件中包含低位非打印字符造成的
處理方法:在產(chǎn)生xml文件的時候,過濾低位非打印字符

把一個字符串中的 低序位 ASCII 字符 替換成 &#x 字符
轉(zhuǎn)換 ASCII 0 - 8 -> &#x0 - &#x8
轉(zhuǎn)換 ASCII 11 - 12 -> &#xB - &#xC
轉(zhuǎn)換 ASCII 14 - 31 -> &#xE - &#x1F


簡單的處理方法
return System.Text.RegularExpressions.Regex.Replace(HttpUtility.HtmlEncode(str),@"[\x00-\x08]|[\x0B-\x0C]|[\x0E-\x1F]", "");

======================================================================================================================================================

復(fù)雜處理

獲取xml時,出現(xiàn)“(十六進(jìn)制值 0x1F)是無效的字符之類Xml異常的解決辦法2008-12-19 10:44最近做新聞采集器,需要獲取很多站點的xml,加載個別站點經(jīng)常出現(xiàn)“(十六進(jìn)制值 0x1F)是無效的字符”問題,百思不的其解。對于問題站點xml的處理,開始的思路是既然直接用 XmlDocument對象的Load()方法不行,就用LoadXML() ,用HttpWebRequest 獲取url讀到流里再轉(zhuǎn)為xml,中間可以加一些非有效字符的過濾處理,但仍然無效,僅僅解決了請求超時的問題...

問題擱置了1周后,終于在今天解決了。

其實很簡單,只加一條語句就搞定了

XmlDocument doc = new XmlDocument();

doc.Normalize();

         // 摘要:
        //     將此 XmlNode 下子樹完全深度中的所有 XmlText 節(jié)點都轉(zhuǎn)換成“正?!毙问?,在這種形式中只有標(biāo)記(即標(biāo)記、注釋、處理指令、CDATA
        //     節(jié)和實體引用)分隔 XmlText 節(jié)點,也就是說,沒有相鄰的 XmlText 節(jié)點。

以下是轉(zhuǎn)一位仁兄的貼:

最近碰到一個問題,我的一個把數(shù)據(jù)庫中記錄的信息暴露出來的Web Service調(diào)用時候出問題了。報下面的錯誤信息:

System.InvalidOperationException was unhandled
Message="XML 文檔(1, 823)中有錯誤。"
Source="System.Xml"
 Message="“”(十六進(jìn)制值 0x0E)是無效的字符。 行 1,位置 823。"
 Source="System.Xml"

當(dāng)這個錯誤發(fā)生時,Web Service 服務(wù)器端不會有任何錯誤,而調(diào)用這個 Web Service 的客戶端則會報上述錯誤。
是何原因?qū)е碌倪@個問題呢?
答案很簡單,是WEB Service 暴露的XML文檔中存在低序位非打印 ASCII 字符所致。
我們查看 Web Service 返回的XML 文檔文檔中,會有下面的XML文檔節(jié):其中的 就是低序位 ASCII 字符。 對應(yīng)的字符如后:

<Value> 在神奇天地裏誰叱咤風(fēng)雨</Value>

會導(dǎo)致這些問題的 低序位非打印 ASCII 字符包含以下字符:
#x0 - #x8 (ASCII 0 - 8)
#xB - #xC (ASCII 11 - 12)
#xE - #x1F (ASCII 14 - 31)

下面就是一個簡單演示這個問題的控制臺程序,
為了簡單起見,這里沒有建立 WebService, 而是把一個類XML序列化存儲到文件,然后再把這個文件反序列化讀取出來:
其中的這個類的Value值中,放了一個低序位非打印 ASCII 字符。
執(zhí)行這個控制臺程序,就會報異常。“XML 文檔(3, 12)中有錯誤?!?/p>

using System;
using System.Xml.Serialization;
using System.IO;
using System.Text;
using System.Globalization;
namespace TextSerialize
{
[Serializable]
public class MyClass
{
public string Value { get; set; }
}
class Program
{
static void Main(string[] args)
{
string fileName = "d:\\1.txt";
MyClass c = new MyClass();
c.Value = string.Format("在神奇{0}天地裏誰叱咤風(fēng)雨", Convert.ToChar(14));
SaveAsXML(c, fileName, Encoding.UTF8);
object o = ConvertFileToObject(fileName, typeof(MyClass), Encoding.UTF8);
MyClass d = o as MyClass;
if (d != null) Console.WriteLine(d.Value);
else Console.WriteLine("null");
Console.ReadLine();
}
/// <summary>
/// 序列化
/// </summary>
/// <param name="objectToConvert"></param>
/// <param name="path"></param>
/// <param name="encoding"></param>
public static void SaveAsXML(object objectToConvert, string path, Encoding encoding)
{
if (objectToConvert != null)
{
Type t = objectToConvert.GetType();
XmlSerializer ser = new XmlSerializer(t);
using (StreamWriter writer = new StreamWriter(path, false, encoding))
{
ser.Serialize(writer, objectToConvert);
writer.Close();
}
}
}
/// <summary>
/// 反序列化
/// </summary>
/// <param name="path"></param>
/// <param name="objectType"></param>
/// <param name="encoding"></param>
/// <returns></returns>
public static object ConvertFileToObject(string path, Type objectType, Encoding encoding)
{
object convertedObject = null;
if (!string.IsNullOrEmpty(path))
{
XmlSerializer ser = new XmlSerializer(objectType);
using (StreamReader reader = new StreamReader(path, encoding))
{
convertedObject = ser.Deserialize(reader);
reader.Close();
}
}
return convertedObject;
}
}
}

上面提到的Web Service 的那個問題,跟這個演示程序是一樣的。

我們需要被序列化的內(nèi)容中,存在 低序位非打印 ASCII 字符 時, .net 會給我們正常序列化, 會自動把 低序位非打印 ASCII 字符 轉(zhuǎn)換成 &#x 編碼的字符(這個XML規(guī)范中要求這么做的)。

但是,反序列化時候,如果需要反序列化的內(nèi)容如果存在 &#x 編碼的字符(映射到低序位非打印 ASCII 字符),則反序列化就會出錯。


如果解決這個問題呢?

當(dāng)然,最徹底的解決方法是修改反序列化的代碼,讓這些字符不會出錯。但這個東西很多時候不歸我們控制。這個方案不可行。

下一個方案就是剔除這些搗亂的字符。

我這里要給出的方案,是對這些字符序列化時作一次預(yù)處理,反序列化時,作一次反向處理。
這里為了演示的更有意義,我這里處理邏輯就是把 低序位非打印 ASCII 字符 轉(zhuǎn)換成 &#x 編碼的字符 ,和把&#x 編碼的字符 轉(zhuǎn)換成 低序位非打印 ASCII 字符。
這樣就可以使用我這里提供的函數(shù),實現(xiàn)更多的處理邏輯。這兩個函數(shù)的代碼如下:

       

/// <summary>
/// 把一個字符串中的 低序位 ASCII 字符 替換成 &#x 字符
/// 轉(zhuǎn)換 ASCII 0 - 8 -> &#x0 - &#x8
/// 轉(zhuǎn)換 ASCII 11 - 12 -> &#xB - &#xC
/// 轉(zhuǎn)換 ASCII 14 - 31 -> &#xE - &#x1F
/// </summary>
/// <param name="tmp"></param>
/// <returns></returns>
public static string ReplaceLowOrderASCIICharacters(string tmp)
{
StringBuilder info = new StringBuilder();
foreach (char cc in tmp)
{
int ss = (int)cc;
if (((ss >= 0) && (ss <= 8)) || ((ss >= 11) && (ss <= 12)) || ((ss >= 14) && (ss <= 32)))
info.AppendFormat("&#x{0:X};", ss);
else info.Append(cc);
}
return info.ToString();
}
/// <summary>
/// 把一個字符串中的下列字符替換成 低序位 ASCII 字符
/// 轉(zhuǎn)換 &#x0 - &#x8 -> ASCII 0 - 8
/// 轉(zhuǎn)換 &#xB - &#xC -> ASCII 11 - 12
/// 轉(zhuǎn)換 &#xE - &#x1F -> ASCII 14 - 31
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static string GetLowOrderASCIICharacters(string input)
{
if (string.IsNullOrEmpty(input)) return string.Empty;
int pos, startIndex = 0, len = input.Length;
if (len <= 4) return input;
StringBuilder result = new StringBuilder();
while ((pos = input.IndexOf("&#x", startIndex)) >= 0)
{
bool needReplace = false;
string rOldV = string.Empty, rNewV = string.Empty;
int le = (len - pos < 6) ? len - pos : 6;
int p = input.IndexOf(";", pos, le);
if (p >= 0)
{
rOldV = input.Substring(pos, p - pos + 1);
// 計算 對應(yīng)的低位字符
short ss;
if (short.TryParse(rOldV.Substring(3, p - pos - 3), NumberStyles.AllowHexSpecifier, null, out ss))
{
if (((ss >= 0) && (ss <= 8)) || ((ss >= 11) && (ss <= 12)) || ((ss >= 14) && (ss <= 32)))
{
needReplace = true;
rNewV = Convert.ToChar(ss).ToString();
}
}
pos = p + 1;
}
else pos += le;
string part = input.Substring(startIndex, pos - startIndex);
if (needReplace) result.Append(part.Replace(rOldV, rNewV));
else result.Append(part);
startIndex = pos;
}
result.Append(input.Substring(startIndex));
return result.ToString();
}


這樣,我們這個演示程序的 Main 函數(shù)修改為下面的代碼,也不會有任何錯誤發(fā)生。

 static void Main(string[] args)
{
Console.WriteLine(GetLowOrderASCIICharacters("123456&#x50000"));
Console.WriteLine(GetLowOrderASCIICharacters("123456&#x5"));
Console.WriteLine(GetLowOrderASCIICharacters("&#x5"));
Console.WriteLine(GetLowOrderASCIICharacters("0123 456789"));
Console.WriteLine(GetLowOrderASCIICharacters("\f"));
Console.WriteLine(GetLowOrderASCIICharacters(" =-1"));
Console.WriteLine(GetLowOrderASCIICharacters(" "));
Console.WriteLine(GetLowOrderASCIICharacters(" "));
string fileName = "d:\\1.txt";
MyClass c = new MyClass();
c.Value = string.Format("在神奇{0}天地裏誰叱咤風(fēng)雨", Convert.ToChar(14));
c.Value = ReplaceLowOrderASCIICharacters(c.Value);
SaveAsXML(c, fileName, Encoding.UTF8);
object o = ConvertFileToObject(fileName, typeof(MyClass), Encoding.UTF8);
MyClass d = o as MyClass;
if (d != null)
{
d.Value = GetLowOrderASCIICharacters(d.Value);
Console.WriteLine(d.Value);
}
else Console.WriteLine("null");
Console.ReadLine();
}

相關(guān)文章

  • C# Winform TextBox控件多行輸入方式

    C# Winform TextBox控件多行輸入方式

    這篇文章主要介紹了C# Winform TextBox控件多行輸入方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • C#實現(xiàn)簡單的Login窗口實例

    C#實現(xiàn)簡單的Login窗口實例

    這篇文章主要介紹了C#實現(xiàn)簡單的Login窗口,實例分析了C#顯示及關(guān)閉登陸Login窗口的技巧,非常具有實用價值,需要的朋友可以參考下
    2015-08-08
  • C# DataTable的詳細(xì)用法分享

    C# DataTable的詳細(xì)用法分享

    在項目中經(jīng)常用到DataTable,如果DataTable使用得當(dāng),不僅能使程序簡潔實用,而且能夠提高性能,達(dá)到事半功倍的效果,現(xiàn)對DataTable的使用技巧進(jìn)行一下總結(jié)
    2013-11-11
  • C# 異步返回類型的幾種方式

    C# 異步返回類型的幾種方式

    異步編程已經(jīng)成為一種重要的編程范式,本文主要介紹了C#異步返回類型的幾種方式,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-03-03
  • C#實現(xiàn)遠(yuǎn)程連接ORACLE數(shù)據(jù)庫的方法

    C#實現(xiàn)遠(yuǎn)程連接ORACLE數(shù)據(jù)庫的方法

    這篇文章主要介紹了C#實現(xiàn)遠(yuǎn)程連接ORACLE數(shù)據(jù)庫的方法,通過自定義函數(shù)db_connection_test實現(xiàn)遠(yuǎn)程連接Oracle數(shù)據(jù)庫的功能,是非常實用的技巧,需要的朋友可以參考下
    2014-12-12
  • C#中感嘆號(!)的一些常見用法小結(jié)

    C#中感嘆號(!)的一些常見用法小結(jié)

    在C#中,感嘆號(!)有多種用途,具體取決于上下,文本文主要介紹了C#中感嘆號(!)的一些常見用法小結(jié),具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • C#獲取目錄最后訪問時間的方法

    C#獲取目錄最后訪問時間的方法

    這篇文章主要介紹了C#獲取目錄最后訪問時間的方法,涉及C#中LastAccessTime方法的使用技巧,需要的朋友可以參考下
    2015-04-04
  • Winform窗體縮放下使用剪切板功能出現(xiàn)頁面閃動解決分析

    Winform窗體縮放下使用剪切板功能出現(xiàn)頁面閃動解決分析

    這篇文章主要介紹了Winform窗體縮放下使用剪切板功能出現(xiàn)頁面閃動解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • C#使用MathNet生成矩陣并打印矩陣元素

    C#使用MathNet生成矩陣并打印矩陣元素

    MathNet.Numerics中提供了線性代數(shù)、微積分、特殊函數(shù)、概率論、隨機函數(shù)、插值、最優(yōu)化等一系列功能,是.net技術(shù)中首選的數(shù)值計算包,本文給大家介紹了C#如何使用MathNet生成矩陣并打印矩陣元素,文中通過代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • C#?輸出參數(shù)out問題

    C#?輸出參數(shù)out問題

    這篇文章主要介紹了C#?輸出參數(shù)out問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評論

沁阳市| 霍州市| 和田县| 昌邑市| 南宫市| 随州市| 华坪县| 尚志市| 安庆市| 南城县| 成武县| 新乡市| 永春县| 额尔古纳市| 昌宁县| 东平县| 汪清县| 青神县| 贞丰县| 武宁县| 襄城县| 托里县| 新源县| 宜州市| 调兵山市| 黑龙江省| 吴忠市| 韶关市| 大埔区| 龙山县| 哈密市| 河间市| 文登市| 罗定市| 比如县| 报价| 上虞市| 曲阳县| 湘乡市| 湄潭县| 裕民县|