xml对象转换成Dictionary或者list

最新类库,请访问https://github.com/twtyypmb/KeyValueEx



对于xml对象有时候要转换成字典对象更容易读取和操作,而字典对象有个问题,就是不能有重复的键,所以对于这种情况就用list来代替,以下为代码

        /// <summary>
        /// xml文档对象转换到Dictionary<string,object>或list
        /// 拥有重复名称子节点的节点会被转换成list,而忽略子节点的名称
        /// </summary>
        /// <param name="xml_doc">xml文档对象</param>
        /// <param name="dso">保存Dictionary的对象</param>
        public static void XmlToDictionaryOrList( XmlDocument xml_doc, object dso )
        {
            if( xml_doc == null || xml_doc.DocumentElement == null || dso == null )
            {
                return;
            }

            XmlToDictionaryOrListWithOutAttributes( xml_doc.DocumentElement, dso );
        }

        /// <summary>
        /// 转换当前节点为字典或list
        /// </summary>
        /// <param name="xn"></param>
        /// <param name="dso"></param>
        private static void XmlToDictionaryOrListWithOutAttributes( XmlNode xn, object dso )
        {

            XmlNodeList xnl = xn.ChildNodes;
            List<object> list = null;
            Dictionary<string, object> dic = null;

            if( dso is Dictionary<string, object> )
            {
                dic = dso as Dictionary<string, object>;
            }
            else
            {
                list = dso as List<object>;
            }

            object temp = null;


            // 如果没有子节点了,退出递归的条件
            // 后一个条件是为了忽略xml的强制数据条件<![CDATA[...]]>,不把它当作子节点处理
            if( xnl.Count == 0 || xn.InnerText == xn.InnerXml )
            {
                //如果本节点是字典类型
                if( dic != null )
                {
                    // 添加键值对
                    dic.Add( xn.Name, xn.InnerText );
                }
                // 如果本节点是list类型,直接添加值,忽略键
                else if( list != null )
                {
                    list.Add( xn.InnerText );
                }
                else
                {
                    throw new Exception( "转换失败" );
                }

                return;
            }
            else
            {
                // 如果有重复的子节点
                if( XmlNodeHasDuplicateChild( xn ) )
                {
                    // 装子节点的对象为list
                    temp = new List<object>();
                }
                else
                {
                    temp = new Dictionary<string, object>();
                }

                if( dic != null )
                {
                    // 以空字典添加节点
                    dic.Add( xn.Name, temp );
                }
                else if( list != null )
                {

                    list.Add( temp );
                }
                else
                {
                    throw new Exception( "转换失败" );
                }

            }


            // 子节点递归
            for( int i = 0; i < xnl.Count; i++ )
            {
                XmlToDictionaryOrListWithOutAttributes( xnl[i], temp );
            }
        }


        /// <summary>
        /// XmlNode下有无重复子节点
        /// </summary>
        /// <param name="xn"></param>
        /// <returns></returns>
        public static bool XmlNodeHasDuplicateChild( XmlNode xn )
        {

            Dictionary<string, string> temp = new Dictionary<string, string>();

            for( int i = 0; i < xn.ChildNodes.Count; i++ )
            {
                if( temp.ContainsKey( xn.ChildNodes[i].Name ) )
                {
                    return true;
                }
                temp[xn.ChildNodes[i].Name] = "呵呵";
            }

            return false;
        }



第一个是入口函数,第二个是节点递归,第三个是辅助函数,对于这个转换函数有个地方要注意,某个节点的子节点一旦有相同名称,不管是全部相同,还是部分相同,都会把这个节点变成list,不过部分相同的情况应该比较少吧,谁会设计这种蛋疼的格式呢?

欢迎指正,希望对大家有用

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值