xml对象转换成Dictionary或者list

对于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,不过部分相同的情况应该比较少吧,谁会设计这种蛋疼的格式呢?

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

相关文章

php输出xml格式字符串
J2ME Mobile 3D入门教程系列文章之一
XML轻松学习手册
XML入门的常见问题(一)
XML入门的常见问题(三)
XML轻松学习手册(2)XML概念