C# XML反序列化,及轉換錯誤的解決方法(空值,數組等)


目錄

轉換方法

問題及解決

問題:數值類型為空時, 轉換出錯

問題:在轉換帶有列表的節點時識別錯誤(list,數組)

問題:在XML序列化時怎樣判斷 必填屬性是否被填寫

問題:當類賦值后,轉換為xml的字符串中 節點多了xmlns屬性

xml序列化時類的自定義屬性

空值標識:IsNullable

指定序列化名稱:ElementName

取消字段的正反序列化:[XmlIgnore]

轉換方法

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
 
namespace WindowsFormsApplication1
{
    class XmlSerializeHelper
    {
        #region 使用演示
        //aaa  類名
        //Example 實例名
        //strxml xml字符串
        
        string strxml;
        //反序列化演示
        //aaa Example = XmlSerializeHelper.DESerializer<aaa>(strxml); 
        //序列化演示
        //string strxml = XmlSerializeHelper.XmlSerialize<aaa>(Example);
        #endregion
 
        /// <summary>
        /// 實體類轉換成XML
        /// </summary>
        /// <typeparam name="T">類名</typeparam>
        /// <param name="obj">T類名的實例</param>
        /// <returns></returns>
        public static string XmlSerialize<T>(T obj)
        {
            using (StringWriter sw = new StringWriter())
            {
                Type t = obj.GetType();
                XmlSerializer serializer = new XmlSerializer(obj.GetType());
                serializer.Serialize(sw, obj);
                sw.Close();
                return sw.ToString();
            }
        }
        
 
 
 
        /// <summary>
        /// XML轉換成實體類-方法1
        /// </summary>
        /// <typeparam name="T">對應的類</typeparam>
        /// <param name="strXML">XML字符串</param>
        /// <returns></returns>
        public static T DESerializer<T>(string strXML) where T : class
        {
            try
            {
                using (StringReader sr = new StringReader(strXML))
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(T));
                    return serializer.Deserialize(sr) as T;
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }
 
        /// <summary>
        /// XML轉換成實體類-方法2
        /// </summary>
        /// <param name="xmlStr"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object DeserializeFromXml(string xmlStr, Type type)
        {
            try
            {
                using (StringReader sr = new StringReader(xmlStr))
                {
                    XmlSerializer xs = new XmlSerializer(type);
                    return xs.Deserialize(sr);
                }
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }
        //Request
        //
 
 
    }
}

小技巧:在建立xml對應類時可自動建立,方法如下:

將完整的XML文本復制下來
新建一個類,將光標放在准備粘貼的位置
點擊VS左上角的 [編輯] - [選擇性粘貼] - [將XML粘貼為類]

注:如果沒有 [將xml粘貼為類] 的選項,右鍵  將 項目-屬性-應用程序 中的目標框架改為.NET Framework 4.5 即可。(東經115注:若本來就是4.5,則需要安裝組件,位置在菜單:工具>獲取工具或功能>單個組件>Web開發工具和.NET Core)

問題及解決
問題:數值類型為空時, 轉換出錯

在轉換后的實體類中,有些屬性因為業務需求,需要修改類型為Int32,Uint32等數字類型,但是給出的xml文本中,此項可能會沒有值,導致在反序列化時會出錯(即使在get方法中容錯也不行)

解決:因為在反序列化的時候接受的屬性是數字類型且xml文本中為空,就會出錯,無論是否在get方法中容錯;所以用屬性類型為string的屬性進行反序列化的對接,具體容錯和賦值可在該string類型內的get方法中進行(可賦值給其他數值類型屬性,string類型屬性僅當做反序列化時的對接口),具體操作如下
舉例說明:反序列化的類中有屬性int num 和 string str 兩個屬性

查看代碼

//對應的實體類
public partial class aaa
    {
        public string str { get; set; }
 
        [XmlIgnore]//取消反序列化
        public int num;
 
        //用string類型的屬性來反序列化,將值轉賦給原數值屬性num
        [XmlElement(ElementName = "num")]//反序列化對應的屬性名
        public string numStr
        {
            get
            {
                return this.num.ToString();
            }
            set
            {
                Int32 num1;
                Int32.TryParse(value.ToString(), out num1);
                this.num = num1;
            }
        }
        
    }


注意:在XML反序列化中對應的類的屬性必須為public才能被反序列化,private不能被反序列化

 

問題:在轉換帶有列表的節點時識別錯誤(list,數組)

解決:在列表標簽下加2個及以上的子循環標簽,進行轉換時即可自動轉換為數組
舉例說明:轉換對照

查看代碼

<eee:qqq xmlns:rrr="http://rrr" xmlns:eee="http://eee">
  <eee:vvv>
    <!--重復1-->
    <eee:mmm />
    <!--重復2-->
    <eee:mmm />
  </eee:vvv>
</eee:qqq>
生成結果: 

/// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://eee")]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://eee", IsNullable = false)]
    public partial class qqq
    {
        private object[] vvvField;
 
        /// <remarks/>
        //public List<object> vvv { get; set; }
        [System.Xml.Serialization.XmlArrayItemAttribute("mmm", IsNullable = false)]
        public object[] vvv
        {
            get
            {
                return this.vvvField;
            }
            set
            {
                this.vvvField = value;
            }
        }
        
    }

 
問題:在XML序列化時怎樣判斷 必填屬性是否被填寫

解決:利用自定義屬性和get方法,
1.將需要必填的類中屬性添加 IsNullable = true 的自定義屬性,當序列化為xml后,為null的屬性的節點標簽有 xsi:nil="true" 屬性顯示
2.將需要必填的類中屬性的get方法中添加約束,如果value為空時添加標識
3.在序列化后的XML中查找指定的標識,即可判斷必填屬性是否都已填寫
所需方法:

查看代碼

/// <summary>
/// 檢查是否存在必填項未填錯誤
/// </summary>
/// <param name="XmlStr">帶有標識,從類中轉換出的xml數據</param>
/// <param name="ErrorKeyword">指定錯誤標識</param>
/// <returns></returns>
private static bool IsRequiredItemError(string XmlStr, string ErrorKeyword)
{
    XDocument xmlDocument = XDocument.Parse(XmlStr);
    //查詢指定空識別
    if (XmlStr.Contains(ErrorKeyword))
    {
        return true;
    }
    //遍歷節點屬性是否有空
    List<XElement> elementList = new List<XElement>();
    GetElements(xmlDocument.Root.Elements(), "Objects", elementList, "Left");
    List<XAttribute> XAList = GetXattributes(elementList);
 
    foreach (XAttribute item in XAList)
    {
        string XAname = item.Name.LocalName;
        string XAvalue = item.Value;
        if (XAname == "nil" && XAvalue=="true")
        {
            return true;
        }
    }
    return false;
}
 
/// <summary>
/// 獲取所有節點的所有屬性
/// </summary>
/// <param name="elementList"></param>
/// <returns></returns>
public static List<XAttribute> GetXattributes(List<XElement> elementList)
{
    List<XAttribute> LXA = new List<XAttribute>();
    foreach (XElement item in elementList)
    {
        IEnumerable<XAttribute> dd = item.Attributes();
        var ie = dd.GetEnumerator();                      // 通過GetEnumerator()方法返回IEnumerator迭代器
        while (ie.MoveNext())
        {
            XAttribute XA = ie.Current;
            LXA.Add(XA);
        }
    }
    return LXA;
}
 
 
 
/// <summary>
/// 獲取嵌套遍歷XML中所有節點
/// </summary>
/// <param name="xElements"></param>
/// <param name="parentNodeName"></param>
/// <param name="elementList">接收</param>
/// <param name="dictionaryValue"></param>
public static void GetElements(IEnumerable<XElement> xElements, string parentNodeName, List<XElement> elementList, string dictionaryValue)
{
    foreach (XElement item in xElements)
    {
        if (item.HasElements)
        {
            GetElements(item.Elements(), parentNodeName + item.Name.ToString(), elementList, dictionaryValue);
        }
        else
        {
            elementList.Add(item);
        }
    }
}

使用:

//讀取XML
string inputtext = System.IO.File.ReadAllText("./XMLFile1.xml");
//將xml轉換為類再轉換為xml(可將必填項設置標識)
string sttt = XmlSerializeHelper.XmlSerialize(XmlSerializeHelper.DeserializeFromXml(inputtext, typeof(qqq)), Encoding.UTF8, new Dictionary<string, string>());
//必填項是否通還有空值
bool BL = IsRequiredItemError(sttt, "標識");
//需要注意的是,數組為空時不會被標注出來,如果大家有什么好的方法的話 歡迎留言


問題:當類賦值后,轉換為xml的字符串中 節點多了xmlns屬性

原因:當給類中Object類型的屬性賦值時, 節點就會自動添加xmlns屬性

解決:將Object類型改為string類型即可

xml序列化時類的自定義屬性
空值標識:IsNullable

[XmlElement(IsNullable = true)]   當示例轉為XML文本時,帶有此自定義屬性的屬性如果為null則會生成  xsi:nil = true 的屬性
 
使用方式:[XmlElement(IsNullable = true)]
        public string Str
 
生成結果:<str xsi:nil="true" />
注意:標識一定要寫在屬性上,不能寫在類上,必須寫在類內的屬性上!!!


指定序列化名稱:ElementName

[XmlElement(ElementName = "str")]
public string aaastr
 
序列化結果: <str/>
 注: 不同參數間可以用"," 間隔 如: [XmlElement(ElementName = "str", IsNullable = true)]

取消字段的正反序列化:[XmlIgnore]

使用方法: 在需要忽略序列化的字段上加上[XmlIgnore]即可
        [XmlIgnore]
        public string Str
————————————————
版權聲明:本文為CSDN博主「幻世頑靈」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/www89574622/article/details/104679730


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM