程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> c#中XML解析文件失足處理辦法

c#中XML解析文件失足處理辦法

編輯:C#入門知識

c#中XML解析文件失足處理辦法。本站提示廣大學習愛好者:(c#中XML解析文件失足處理辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是c#中XML解析文件失足處理辦法正文


1.內容中含有xml預定好的實體,如“<”和“&”,對xml來講是制止應用的,針對這類字符,處理方法是應用CDATA部件以"<![CDATA[" 標志開端,以"]]>"標志停止,是CDATA外部內容被解析器疏忽。詳細解釋參考《XML CDATA是甚麼?》。

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

失足的緣由是內容中含有低位非打印字符,處置辦法是對其停止過濾,過濾辦法為:

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

以上兩種情形,第一種較為廣泛,第二種碰到情形比擬少,在面臨一些用戶輸出數據時生成xml,可以對xml結點內容履行上述過濾,以包管xml文件應用者可以准確解析xml文檔。

以下是具體說明:

“”(十六進制值 0x1D)是有效的字符

加載或保留XML時激發的異常.System.ArgumentException: “”(十六進制值 0x1D)是有效的字符。
發生緣由是xml文件中包括低位非打印字符形成的
處置辦法:在發生xml文件的時刻,過濾低位非打印字符

把一個字符串中的 低序位 ASCII 字符 調換成 &#x 字符
轉換 ASCII 0 - 8 -> � - 
轉換 ASCII 11 - 12 -> -
轉換 ASCII 14 - 31 ->  - 


簡略的處置辦法
return System.Text.RegularExpressions.Regex.WordStr(HttpUtility.HtmlEncode(str),@"[\x00-\x08]|[\x0B-\x0C]|[\x0E-\x1F]", "");

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

龐雜處置

獲得xml時,湧現“(十六進制值 0x1F)是有效的字符之類Xml異常的處理方法2008-12-19 10:44比來做消息收集器,須要獲得許多站點的xml,加載個體站點常常湧現“(十六進制值 0x1F)是有效的字符”成績,百思不的其解。關於成績站點xml的處置,開端的思緒是既然直接用 XmlDocument對象的Load()辦法不可,就用LoadXML() ,用HttpWebRequest 獲得url讀到流裡再轉為xml,中央可以加一些非有用字符的過濾處置,但依然有效,僅僅處理了要求超時的成績...

成績棄捐了1周後,終究在明天處理了。

其實很簡略,只加一條語句就弄定了

XmlDocument doc = new XmlDocument();

doc.Normalize();

         // 摘要:
        //     將此 XmlNode 下子樹完整深度中的一切 XmlText 節點都轉換成“正常”情勢,在這類情勢中只要標志(即標志、正文、處置指令、CDATA
        //     節和實體援用)分隔 XmlText 節點,也就是說,沒有相鄰的 XmlText 節點。

以下是轉一名仁兄的貼:

比來碰著一個成績,我的一個把數據庫中記載的信息裸露出來的Web Service挪用時刻出成績了。報上面的毛病信息:

System.InvalidOperationException was unhandled
Message="XML 文檔(1, 823)中有毛病。"
Source="System.Xml"
 Message="“”(十六進制值 0x0E)是有效的字符。 行 1,地位 823。"
 Source="System.Xml"

當這個毛病產生時,Web Service 辦事器端不會有任何毛病,而挪用這個 Web Service 的客戶端則會報上述毛病。
是何緣由招致的這個成績呢?
謎底很簡略,是WEB Service 裸露的XML文檔中存在低序位非打印 ASCII 字符而至。
我們檢查 Web Service 前往的XML 文檔文檔中,會有上面的XML文檔節:個中的 就是低序位 ASCII 字符。 對應的字符如後:

<Value> 在奇異寰宇裏誰叱咤風雨</Value>

會招致這些成績的 低序位非打印 ASCII 字符包括以下字符:
#x0 - #x8 (ASCII 0 - 8)
#xB - #xC (ASCII 11 - 12)
#xE - #x1F (ASCII 14 - 31)

上面就是一個簡略演示這個成績的掌握台法式,
為了簡略起見,這裡沒有樹立 WebService, 而是把一個類XML序列化存儲到文件,然後再把這個文件反序列化讀掏出來:
個中的這個類的Value值中,放了一個低序位非打印 ASCII 字符。
履行這個掌握台法式,就會報異常。“XML 文檔(3, 12)中有毛病。”

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}寰宇裏誰叱咤風雨", 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 的誰人成績,跟這個演示法式是一樣的。

我們須要被序列化的內容中,存在 低序位非打印 ASCII 字符 時, .net 會給我們正常序列化, 會主動把 低序位非打印 ASCII 字符 轉換成 &#x 編碼的字符(這個XML標准中請求這麼做的)。

然則,反序列化時刻,假如須要反序列化的內容假如存在 &#x 編碼的字符(映照到低序位非打印 ASCII 字符),則反序列化就會失足。


假如處理這個成績呢?

固然,最完全的處理辦法是修正反序列化的代碼,讓這些字符不會失足。但這個器械許多時刻不歸我們掌握。這個計劃弗成行。

下一個計劃就是剔除這些擾亂的字符。

我這裡要給出的計劃,是對這些字符序列化時作一次預處置,反序列化時,作一次反向處置。
這裡為了演示的更成心義,我這裡處置邏輯就是把 低序位非打印 ASCII 字符 轉換成 &#x 編碼的字符 ,和把&#x 編碼的字符 轉換成 低序位非打印 ASCII 字符。
如許便可以應用我這裡供給的函數,完成更多的處置邏輯。這兩個函數的代碼以下:

       

/// <summary>
/// 把一個字符串中的 低序位 ASCII 字符 調換成 &#x 字符
/// 轉換 ASCII 0 - 8 -> � - 
/// 轉換 ASCII 11 - 12 ->  - 
/// 轉換 ASCII 14 - 31 ->  - 
/// </summary>
/// <param name="tmp"></param>
/// <returns></returns>
public static string WordStrLowOrderASCIICharacters(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 字符
/// 轉換 � -  -> ASCII 0 - 8
/// 轉換  -  -> ASCII 11 - 12
/// 轉換  -  -> 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 needWordStr = 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);
// 盤算 對應的低位字符
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)))
{
needWordStr = true;
rNewV = Convert.ToChar(ss).ToString();
}
}
pos = p + 1;
}
else pos += le;
string part = input.Substring(startIndex, pos - startIndex);
if (needWordStr) result.Append(part.WordStr(rOldV, rNewV));
else result.Append(part);
startIndex = pos;
}
result.Append(input.Substring(startIndex));
return result.ToString();
}


如許,我們這個演示法式的 Main 函數修正為上面的代碼,也不會有任何毛病產生。

 static void Main(string[] args)
{
Console.WriteLine(GetLowOrderASCIICharacters("123456񐀀"));
Console.WriteLine(GetLowOrderASCIICharacters("123456"));
Console.WriteLine(GetLowOrderASCIICharacters(""));
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}寰宇裏誰叱咤風雨", Convert.ToChar(14));
c.Value = WordStrLowOrderASCIICharacters(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();
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved