C# XML反序列化,及转换错误的解决方法(空值,数组等)
目录
问题:当类赋值后,转换为xml的字符串中 节点多了xmlns属性
转换方法
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
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步