Xml序列化和反序列化功能應用已於《 XML序列化(Serialize)與反序列化(Deserialize) – 上篇 》詳細介紹示範過,但是有時候僅知道Xml格式內容的字串,並沒有Xml檔案,在程式開發上也常常需要轉換為物件,以利於程序處理,這時該如何進行轉換? Xml序列化技術應用極廣,最近於公司簡訊的發送SMS、MMS專案,以及新產品NAS (網路儲存伺服器)的應用程式,在開發上皆有使用到這些技術。以下例子為使用Xml字串進行序列化和反序列化的功能示範。
如何序列化取得Xml字串內容
若只想取得序列化物件資料內容,並不想儲存為Xml檔案,序列化時可使用StringWriter方式達到目的,示範程式碼如下例子所示:
- 序列化取得Xml字串內容
/// <summary> /// 取得類別序列化的XML格式字串 /// </summary> /// <param name="obj"></param> /// <returns></returns> public static string SerializeToString(object obj) { string xmlString = string.Empty; StringWriter writer = null; try { XmlSerializer xml = new XmlSerializer(obj.GetType()); writer = new StringWriter(); xml.Serialize(writer, obj); xmlString = writer.ToString(); } catch (Exception ex) { throw ex; } finally { writer.Close(); } return xmlString; }
- 示範用法
Person p = new Person(); p.Name = "M.K."; p.Phone = "0950123456"; string xmlString = XmlSerialize.SerializeToString(p);
- 執行結果 – xmlString內容
<?xml version="1.0" encoding="utf-16"?> <Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Name>M.K.</Name> <Phone>0950123456</Phone> </Person>
- 想移除Xml Namespaces內容,即上述執行結果的「xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=http://www.w3.org/2001/XMLSchema」,可調整SerializeToString方法,於序列化時使用XmlSerializerNamespaces方式達到目的,示範程式碼如下例子所示:
/// <summary> /// 取得類別序列化的XML格式字串 /// </summary> /// <param name="obj"></param> /// <returns></returns> public static string SerializeToString(object obj) { string xmlString = string.Empty; StringWriter writer = null; try { XmlSerializer xml = new XmlSerializer(obj.GetType()); writer = new StringWriter(); XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(); namespaces.Add(string.Empty, string.Empty); xml.Serialize(writer, obj, namespaces); } catch (Exception ex) { throw ex; } finally { writer.Close(); } return xmlString; }
- 執行結果 – xmlString內容 (已移除Xml命名空間)
<?xml version="1.0" encoding="utf-16"?> <Person> <Name>M.K.</Name> <Phone>0950123456</Phone> </Person>
- 使用泛型寫法並移除Xml宣告與Namespaces內容,於序列化時使用XmlWriter 和XmlSerializerNamespaces方式達到目的,示範程式碼如下例子所示:
- 泛型序列化XML字串
/// <summary> /// 取得類別序列化的XML格式字串,移除XML命名空間。 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="value"></param> /// <returns></returns> public static string SerializeToStringOmitDeclaration<T>(T value) { if (value == null) return null; try { XmlSerializer serializer = new XmlSerializer(typeof(T)); XmlWriterSettings settings = new XmlWriterSettings(); settings.OmitXmlDeclaration = true; using (StringWriter textWriter = new StringWriter()) { using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings)) { XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(); namespaces.Add("", ""); serializer.Serialize(xmlWriter, value, namespaces); } return textWriter.ToString(); } } catch (Exception ex) { return null; } }
- 示範用法
Person p = new Person();
p.Name = "M.K.";
p.Phone = "0950123456";
string xmlString = XmlSerialize.SerializeToStringOmitDeclaration<Person>(p);
- 執行結果 – xmlString內容 (已移除Xml宣告與命名空間)
<Person> <Name>M.K.</Name> <Phone>0950123456</Phone> </Person>
如何使用Xml字串反序列化(並移除命名空間)
只有Xml字串內容想使用反序列化方式取得物件資料,示範程式碼如下例子所示:
- 反序列化XML字串
/// <summary> /// 反序列化並移除Namespace資料 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="xmlString"> XML字串內容</param> /// <returns></returns> public static T DeserializeOmitNamespace<T>(string xmlString) { try { XmlSerializer xs = new XmlSerializer(typeof(T)); using (StringReader reader = new StringReader(xmlString)) { object obj = xs.Deserialize(new OmitNamespaceXmlTextReader(reader)); return (T)obj; } } catch (Exception ex) { return default(T); } } public class OmitNamespaceXmlTextReader : XmlTextReader { public OmitNamespaceXmlTextReader(TextReader reader) : base(reader) { } public override string NamespaceURI { get { return ""; } } }
- XML測試字串內容
<?xml version="1.0" encoding="utf-8"?> <Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Name>M.K.</Name> <Phone>0950123456</Phone> </Person>
- 示範用法
// xmlString 為XML測試字串內容 string xmlString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Person xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><Name>M.K.</Name><Phone>0950123456</Phone></Person>"; Person person = XmlSerialize.DeserializeOmitNamespace<Person>(xmlString);
示範例子為寫一個OmitNamespaceXmlTextReader類別去繼承XmlTextReader並覆寫NamespaceURI值為空值,並使用於反序列化以達成移除xml namespaces。
使用MemoryStream將Xml字串反序列化
也可使用MemoryStream寫法反序列化,示範程式碼如下例子所示:
- MemoryStream反序列化XML字串
/// <summary> /// 反序列化XML檔案內容,並使用MemoryStream 處理 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="xmlString"></param> /// <returns></returns> public static T DeserializeUseMemory<T>(string xmlString) { try { using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xmlString))) { XmlSerializer xs = new XmlSerializer(typeof(T)); object obj = xs.Deserialize(ms); return (T)obj; } } catch (Exception ex) { return default(T); } }
- 示範用法
// xmlString 為XML測試字串內容 string xmlString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Person xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><Name>M.K.</Name><Phone>0950123456</Phone></Person>"; Person person = XmlSerialize.DeserializeUseMemory<Person>(xmlString);
MSDN參考資料
stackoverflow參考資料
Using StringWriter for XML Serialization
Can I make XmlSerializer ignore the namespace on deserialization?
相關資料
[C#.NET] 序列化到MemoryStream