码迷,mamicode.com
首页 > Windows程序 > 详细

C#.NET 程序员的福利,自己写的一个XML操作类,可实现像jquery一样方便的xml操作,且不用专门去处理命名空间。

时间:2017-07-18 15:38:45      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:star   ret   save   name   定位   class   模糊   命名空间   基础   

此工具是进入一家新公司之后实现的,主要是工作当中操作 xml 的时间太多,因为公司按任务计“工作量”,领导给我安排的时间远远不够完善此工具【悲哀的制度】,虽然我也能直接在cs中直接中规中矩完成,但实在受不了那种重复和低效,所以此工具基础部分绝大部分时间是在家中加班完成,剩下应用于公司项目中之后,在公司改了一些BUG,差不多也用了半年多了,实在是很好用,现在也差不多稳定了,特分享出来,需要的直接拿去用吧,有BUG可以直接发消息给我沟通,不用谢。。

使用方法:

x(filepath).Find("//abc").Text("abc").Find("//cde").Xml("111");
x("<root><item /></root>").Find("item").Append(x("name").Text("张静"));
x("<root><item /></root>").Find("item").Replace(x("name").Text("张静"));
x("<root><item /></root>").Find("item").Remove();

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Xml.XPath;
using System.Text.RegularExpressions;

namespace com.iwefix.Common
{
    /// 原创: 张静
    /// 由于 c# 中不能声明全局变量 ,所以想实现 jQuery 中的 $(‘xxx‘) 只能用下面的折中办法:
    /// 如: 
    /// class a {
    ///  	//复制下面这一行到引用类中,然后就可以直接使用了。
    /// 	XmlOperV2.LoadHandle x = ((o) => { return XmlOperV2.load(o); });	
    /// 	如果提示 lamada 表达式无法使用,可使用下边这边替换,一样的效果
    /// 	XmlOperV2.LoadHandle x = (delegate(object o) { return XmlOperV2.load(o); });
    ///  	public int method() {
    /// 			Console.WriteLine( x("<root></root>").Append(x("<item>abc</item>")).Xml() );
    /// 		}
    /// }
    public class XmlOperV2
    {
        private delegate bool EachHandle2(XmlNode obj);

        public delegate bool EachHandle(XmlOperV2 oper);

        /// <summary>
        /// XmlOperV2.LoadHandle x = (delegate(object o) { return XmlOperV2.load(o); });
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public delegate XmlOperV2 LoadHandle(Object obj);

        #region 全局变量

        private string oldXml = "";

        /// <summary>
        /// 最初的 xml
        /// </summary>
        /// <value>The old xml.</value>
        public string OldXml
        {
            get
            {
                return oldXml;
            }
        }

        private int index = 0;

        /// <summary>
        /// Find 操作后的位置
        /// </summary>
        public int Index
        {
            get { return index; }
        }

        private int position = -1;

        /// <summary>
        /// 在其父节点中的位置
        /// </summary>
        public int Position
        {
            get
            {
                if (position >= 0)
                {
                    return position;
                }
                else
                {
                    for (int c = 0; c < _first(initObj).ParentNode.ChildNodes.Count; c++)
                    {
                        if (_first(initObj).ParentNode.ChildNodes[c] == _first(initObj))
                        {
                            position = c;
                        }
                    }
                    return position;
                }
            }
        }

        /// <summary>
        /// 最终的 xml
        /// </summary>
        /// <value>The final xml.</value>
        public string OuterXml
        {
            get
            {
                switch (initObj.GetType().Name)
                {
                    case "XmlDocument":
                        return DocmentXml;
                    default:
                        XmlNode n = _first(initObj);
                        if (n != null)
                            return n.OuterXml.Replace("xmlns=\"\"", "");
                        else
                            return "";
                }
            }
        }

        public string DocmentXml
        {
            get
            {
                if (xmlDoc != null)
                    return xmlDoc.OuterXml.Replace("xmlns=\"\"", "");
                else
                    return "";
            }
        }

        //用来保存所有的命名空间,主要是为了处理前缀重复的问题
        private List<KeyValuePair<string, string>> lstXmlNs = new List<KeyValuePair<string, string>>();
        public List<KeyValuePair<string, string>> LstXmlNs {
            get {
                return lstXmlNs;
            }
        }

        private XmlNamespaceManager nsmgr = null;
        public XmlNamespaceManager Nsmgr
        {
            get
            {
                if (nsmgr == null)
                {
                    nsmgr = _getNameTable(this.xmlDoc, ref lstXmlNs);
                    return nsmgr;
                }
                else
                {
                    return nsmgr;
                }
            }
        }

        public int Length
        {
            get
            {
                int ret = 0;
                switch (initObj.GetType().Name)
                {
                    case "XmlNode":
                    case "XmlElement":
                    case "XmlDocument":
                        ret = 1;

                        break;
                    case "XmlNodeList":
                    case "XPathNodeList":
                        ret = ((XmlNodeList)initObj).Count;

                        break;
                    default:
                        if (initObj.GetType() == typeof(List<XmlNode>))
                            ret = ((List<XmlNode>)initObj).Count;
                        else
                            ret = 0;
                        break;
                }

                return ret;
            }
        }

        private XmlDocument xmlDoc = new XmlDocument();
        private object initObj = null;



        #endregion

        #region 构造函数

        private XmlOperV2()
        {
        }

        private XmlOperV2(object obj)
        {
            if (obj.GetType() == typeof(XmlOperV2))
                obj = ((XmlOperV2)obj).initObj;

            switch (obj.GetType().Name)
            {
                case "String":
                    if (string.IsNullOrEmpty(obj.ToString())) throw new Exception("XmlOperV2不能实例化空字符串");
                    try
                    {
                        xmlDoc.LoadXml(obj.ToString());

                        this.oldXml = xmlDoc.OuterXml;
                        this.initObj = xmlDoc;
                    }
                    catch (XmlException ex)
                    {
                        if (ex.Message.IndexOf("有多个根元素") >= 0)  //-2146232000
                        {
                            XmlOperV2 tmp = XmlOperV2.load("root").Xml(obj.ToString());
                            this.oldXml = tmp.Xml();

                            List<XmlNode> lstNodes = new List<XmlNode>();
                            for (var c = 0; c < tmp.Childrens().Length; c++) {
                                lstNodes.Add(tmp.Childrens()[c].CloneNode(true));
                            }

                            this.initObj = lstNodes;
                            tmp = null;
                        }
                        else
                        {
                            if (File.Exists(obj.ToString()))
                            {
                                xmlDoc.Load(obj.ToString());
                            }
                            else if (obj.ToString().IndexOf("<") < 0)
                            {
                                if (obj.ToString().IndexOf("/") < 0)
                                {
                                    xmlDoc.LoadXml("<" + (new Regex(@"(\w+)")).Match(obj.ToString()).Groups[1].Value + " />");
                                }
                                else
                                {
                                    xmlDoc.LoadXml(_makeXmlTree(obj.ToString()));
                                }
                            }
                            else
                            {
                                throw new Exception("XmlOperV2 无法构造对象!");
                            }

                            this.oldXml = xmlDoc.OuterXml;
                            this.initObj = xmlDoc;
                        }
                    }


                    break;
                case "XmlNode":
                case "XmlElement":
                case "XmlDocument":
                    this.oldXml = ((XmlNode)obj).OuterXml;
                    this.initObj = obj;
                    this.xmlDoc = ((XmlNode)obj).OwnerDocument;
                    break;
                case "XmlNodeList":
                case "XPathNodeList":
                    this.initObj = obj;
                    _each(initObj, (o) =>
                    {
                        this.xmlDoc = o.OwnerDocument;
                        return false;
                    });
                    break;
                default:
                    if (obj.GetType().Name.IndexOf("List") >= 0)
                    {
                        this.initObj = obj;
                        _each(initObj, (o) =>
                        {
                            this.xmlDoc = o.OwnerDocument;
                            return false;
                        });
                    }
                    else
                    {
                        throw new Exception("XmlOperV2::XmlOperV2 不接受的构造类型!");
                    }
                    break;
            }
        }

        /// <summary>
        /// 对象类似于 jQuery 的 $($("")[0]) 的作用
        /// 还可以为字符串,
        /// 如果是 "abc" 则会构造成 <abc></abc>
        /// 如果是 "root/item" 则会构造成 <root><item></item></root>
        /// 如果是 "root/item[a=1, innerText=kk]" 则会构造成 <root><item a="1">kk</item></root>
        /// 也可以直接传 xml 字符串 "<root><item></item></root>"
        /// 更复杂的如:"root/item[Name=张静]/(age[innerText=34]|sex[innerText=男])"
        ///     会生成:‘<root><item Name="张静"><age>34</age><sex>男</sex></item></root>‘
        /// </summary>
        /// <param name="o">O.</param>
        public static XmlOperV2 load(object obj)
        {
            XmlOperV2 op = new XmlOperV2(obj);
            op.nsmgr = _getNameTable(op.xmlDoc, ref op.lstXmlNs);
            return op;
        }

        private static XmlOperV2 load(object obj, XmlNamespaceManager nsmgr, int idx)
        {
            XmlOperV2 o = new XmlOperV2(obj);
            o.index = idx;
            o.nsmgr = nsmgr;
            return o;
        }

        #endregion

        #region 公共函数

        public void Each(EachHandle eachCallBack)
        {
            int _index = 0;
            XmlOperV2 me = this;
            _each(initObj, (o) =>
            {
                return eachCallBack(XmlOperV2.load(o, me.nsmgr, _index++));
            });
        }

        /// <summary>
        /// 索引器
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public XmlNode this[int index]
        {
            get
            {
                return _eq(initObj, index);
            }
        }

        /// <summary>
        /// 根据 xpath 查找节点,如果xpath里含有命名空间前缀,且该前缀对应多个命名空间,会一个一个去试。
        /// </summary>
        /// <param name="xpath"></param>
        /// <returns></returns>
        public XmlOperV2 Find(string xpath)
        {
            XmlOperV2 ret = Find(xpath, false);
            if (ret.Length > 0) return ret;

            string[] prefixs = _getXpathPrefix(xpath);
            if (prefixs.Length > 0)
            {
                for (int c = 0; c < prefixs.Length; c++) {
                    var uris = lstXmlNs.FindAll(o => o.Key == prefixs[c]);
                    for (int c2 = 0; c2 < uris.Count; c2++) {
                        var uri = uris[c2];
                        nsmgr.AddNamespace(uri.Key, uri.Value);
                        ret = Find(xpath, false);
                        if (ret.Length > 0) return ret;
                    }
                }
            }

            return ret;
        }


        /// <summary>
        /// nsmgrs 格式,直接复制 xml 中的内容,如:xmlns:m="http://www.chinatelecom.com/IMS/MMTelAS/"
        /// </summary>
        /// <param name="xpath"></param>
        /// <param name="nsmgrs"></param>
        /// <returns></returns>
        public XmlOperV2 Find(string xpath, params string[] nsmgrs)
        {
            object ret = _find(initObj, xpath, false, nsmgr, false, nsmgrs);
            XmlOperV2 oRet = XmlOperV2.load(ret, nsmgr, 0);
            return oRet;
        }

        /// <summary>
        /// fuzzySearch = true, 支持模糊查询, xpath 前加 //,区分大小写
        /// </summary>
        /// <param name="xpath"></param>
        /// <param name="fuzzySearch"></param>
        /// <returns></returns>
        public XmlOperV2 Find(string xpath, bool fuzzySearch)
        {
            object ret = _find(initObj, xpath, fuzzySearch, nsmgr);
            XmlOperV2 oRet = XmlOperV2.load(ret, nsmgr, 0);
            return oRet;
        }

        /// <summary>
        /// fuzzySearch = true, 支持模糊查询, xpath 前加 //,不区分大小写 性能较差
        /// </summary>
        /// <param name="xpath"></param>
        /// <param name="fuzzySearch"></param>
        /// <returns></returns>
        public XmlOperV2 FindIgnoreCase(string xpath)
        {
            return XmlOperV2.load(_find(initObj, xpath, true, null, true), nsmgr, 0);
        }

        public XmlOperV2 First()
        {
            return Eq(0);
        }

        public XmlOperV2 Last()
        {
            return Eq(Length - 1);
        }

        public XmlOperV2 Skip(int n)
        {
            return Between(n, Length - 1);
        }

        public XmlOperV2 Eq(int index)
        {
            return XmlOperV2.load(_eq(initObj, index), nsmgr, 0);
        }

        public XmlOperV2 Childrens()
        {
            return Find("./*");
        }

        /// <summary>
        /// 取值
        /// </summary>
        /// <returns></returns>
        public string Text()
        {
            return _text(initObj);
        }

        public string Xml()
        {
            return _xml(initObj);
        }

        public XmlOperV2 Text(object val)
        {
            _text(initObj, val);
            return this;
        }

        public XmlOperV2 Xml(object xml)
        {
            _xml(initObj, xml);
            return this;
        }

        public XmlOperV2 CDATA(object xml)
        {
            this.Xml("");
            XmlCDataSection cdata = this.xmlDoc.CreateCDataSection(xml.ToString());
            this[0].AppendChild(cdata);
            //_xml(initObj, xml);
            return this;
        } 

        public XmlOperV2 Remove()
        {
            XmlNode pNode = null;
            _each(initObj, (o) =>
            {
                pNode = o.ParentNode;
                o.ParentNode.RemoveChild(o);
                return true;
            });
            this.initObj = new List<XmlNode>();
            return this;
        }

        /// <summary>
        /// 添加一个子节点,当前节点不变,如果需要访问刚才添加的节点,需要 Find
        /// </summary>
        /// <param name="node">Node.</param>
        public XmlOperV2 Append(XmlOperV2 node)
        {
            if (initObj == node.initObj)
                throw new Exception("不能把自己附加给自己");

            if (node.xmlDoc != xmlDoc)
            {
                node.xmlDoc = xmlDoc;
                List<XmlNode> lxn = new List<XmlNode>();
                _each(node.initObj, (o) =>
                {
                    lxn.Add(xmlDoc.ImportNode(o, true));
                    return true;
                });
                node.initObj = lxn;
            }

            _each(node.initObj, (o) =>
            {
                _append(initObj, o);
                return true;
            });

            return this;
        }

        public XmlOperV2 Clone()
        {
            if (this.Length == 1)
            {
                return XmlOperV2.load(this[0].CloneNode(true), nsmgr, 0);
            }
            else
            {
                List<XmlNode> lx = new List<XmlNode>();
                for (int c = 0; c < this.Length; c++)
                {
                    lx.Add(this[c].CloneNode(true));
                }

                XmlOperV2 r = XmlOperV2.load(lx, nsmgr, 0);
                r.position = -1;
                return r;
            }
        }

        /// <summary>
        /// 替换节点,多节点替换多节点要求数量一致!
        /// 单节点替换单节点,多节点替换单节点,单节点替换多节点无要求。
        /// </summary>
        /// <param name="op"></param>
        /// <returns></returns>
        public XmlOperV2 Replace(XmlOperV2 op)
        {
            XmlNode old = this[0];

            //替换根节点
            if (this.initObj.GetType() == typeof(XmlDocument))
            {
                if (op.Length == 1)
                {
                    XmlNode newNode = old.OwnerDocument.ImportNode(op[0], true);
                    this.xmlDoc.RemoveAll();
                    this.xmlDoc.AppendChild(newNode);
                } else {
                    throw new Exception("替换根节点,只能用单节点!");  
                }
            }
            else
            {
                if (old.ParentNode != null) //有些 clone 出来的 XmlNode 是不得 Parent 的。
                {
                    if (this.Length == 1 && op.Length == 1)             //单节点换单节点
                    {
                        XmlNode newNode = old.OwnerDocument.ImportNode(op[0], true);
                        old.ParentNode.ReplaceChild(newNode, old);
                    }
                    else if (this.Length == 1 && op.Length > 1) {       //多节点换单节点
                        _each(op.initObj, delegate(XmlNode node)
                        {
                            XmlNode newNode = old.OwnerDocument.ImportNode(node, true);
                            old.ParentNode.InsertBefore(newNode, old);
                            return true;
                        });
                        old.ParentNode.RemoveChild(old);
                    }
                    else if (this.Length > 1 && op.Length == 1)       //单节点换多节点
                    {   
                        for (var c = 0; c < this.Length; c++)
                        {
                            XmlNode newNode = old.OwnerDocument.ImportNode(op[0], true);
                            this[c].ParentNode.ReplaceChild(newNode, this[c]);
                        }
                    }
                    else
                    {                                                   //多节点换多节点
                        if (this.Length == op.Length)
                        {
                            for (var c = 0; c < this.Length; c++)
                            {
                                XmlNode newNode = old.OwnerDocument.ImportNode(op[c], true);
                                this[c].ParentNode.ReplaceChild(newNode, this[c]);
                            }
                        }
                        else
                        {
                            throw new Exception("节点数组和被替换的数量不一致!");
                        }
                    }
                } else {
                    initObj = op.initObj;  //直接赋值得了
                    xmlDoc = op.xmlDoc;
                }
            }

            return this;
        }

        /// <summary>
        /// 在其后插入节点
        /// </summary>
        /// <param name="op"></param>
        /// <returns></returns>
        public XmlOperV2 InsertAfter(XmlOperV2 op)
        {
            XmlNode src = this[0];
            XmlNode targ = op[0];

            XmlNode newNode = src.OwnerDocument.ImportNode(targ, true);

            if (src.ParentNode != null)
            {
                src.ParentNode.InsertAfter(newNode, src);
            }
            else
            {
                throw new Exception("必须要有父节点");
            }

            return this;
        }

        /// <summary>
        /// 在其后插入节点
        /// </summary>
        /// <param name="op"></param>
        /// <returns></returns>
        public XmlOperV2 InsertBefore(XmlOperV2 op)
        {
            XmlNode src = this[0];
            XmlNode targ = op[0];

            XmlNode newNode = src.OwnerDocument.ImportNode(targ, true);

            if (src.ParentNode != null)
            {
                src.ParentNode.InsertBefore(newNode, src);
            }
            else
            {
                throw new Exception("必须要有父节点");
            }

            return this;
        }



        public XmlOperV2 Parent()
        {
            return XmlOperV2.load(_first(initObj).ParentNode, nsmgr, 0);
        }

        public XmlOperV2 Top(int n)
        {
            return Between(0, n - 1);
        }

        public XmlOperV2 Between(int start, int end)
        {
            return XmlOperV2.load(_between(initObj, start, end), nsmgr, 0);
        }

        public XmlOperV2 AppendTo(XmlOperV2 pNode)
        {
            pNode.Append(this);
            return this;
        }

        public XmlOperV2 RemoveAttr(string attName)
        {
            _removeAttr(initObj, attName);
            return this;
        }

        public string Attr(string attName)
        {
            return _attr(initObj, attName);
        }

        public XmlOperV2 Attr(string attName, object value)
        {
            _attr(initObj, attName, value);
            return this;
        }

        public XmlOperV2 Save(string filePath)
        {
            FileOper.WriteFile(filePath, OuterXml);
            return this;
        }

        #endregion

        #region 内部函数

        /// <summary>
        /// List<XmlNode
        /// </summary>
        /// <param name="obj">Object.</param>
        /// <param name="xpath">Xpath.</param>
        /// <param name="fuzzySearch">If set to <c>true</c> fuzzy search.</param>
        /// <param name="nsmgr">Nsmgr.</param>
        /// <param name="ignoreCase">If set to <c>true</c> ignore case.</param>
        private static object _find(object obj, string xpath, bool fuzzySearch = false, XmlNamespaceManager nsmgr = null, bool ignoreCase = false, params string[] nsmgrs)
        {
            /*  
             * 发现一个 XPath 的使用问题
             * 假设有 <root><item><name id="1" /></item><item><name id="2" /></item></root>
             * XmlNodeRoot.SelectNodes("item")[1].SelectNodes("//name") 应该返回什么呢?
             * 按我的个人理解,应该是返回 <name id="2" /> 的,但是结果返回的是 <name id="1" /><name id="2" />
             * 所以此处需要使用绝对路径来定位,不能随便加 //
             */
            List<XmlNode> xn = null;
            XmlNodeList xnl = null;

            _each(obj, (o) =>
            {
                if (!fuzzySearch)
                {
                    try
                    {
                        try
                        {
                            xnl = o.SelectNodes(xpath);
                            if (xnl.Count > 0) return true;
                        }
                        catch { }

                        if (nsmgr != null)
                        {
                            xnl = o.SelectNodes(xpath, nsmgr);
                            if (xnl.Count <= 0)
                            {
                                for (int c = 0; c < nsmgrs.Length; c++)
                                {
                                    string[] stemp = nsmgrs[c].Split(‘=‘);
                                    if (stemp.Length != 2) throw new Exception("show:格式xmlns=uri,或xmlns:prefix=uri,或prefix=uri");
                                    stemp[0] = stemp[0].Replace("xmlns:", "");
                                    stemp[0] = stemp[0].Replace("xmlns", "");
                                    if (stemp[0] == "") stemp[0] = "xmlnsDefault";
                                    nsmgr.AddNamespace(stemp[0], stemp[1].Replace("\"", ""));
                                }
                                xnl = o.SelectNodes(_makeNSPrefix(xpath), nsmgr);
                            }
                        } 
                    }
                    catch (Exception ex) {
                        if (ex.Message.StartsWith("show:")) throw ex;
                    }
                }
                else
                {
                    if (!xpath.StartsWith("/") && !xpath.StartsWith("./"))
                        xpath = "//" + xpath;

                    if (ignoreCase)
                    {
                        xpath = xpath.ToLower();

                        string newXmlStr = o.OuterXml.ToLower();
                        newXmlStr = (new Regex(@"xmlns[\:]?[^=]*\=\"".*?\""")).Replace(newXmlStr, "");
                        newXmlStr = (new Regex(@"(\s+|<[\/]?)(?:\w+)\:")).Replace(newXmlStr, "$1");
                        XmlNode newXml = XmlOperV2.load(newXmlStr)[0];

                        XmlNodeList _xnl = newXml.SelectNodes(xpath);
                        /* 这个算法有问题,只考虑到了连续的节点,不过算是个思路                   
                        string firstPos = getNodePosition(newXml, _first(xnl), 0); //找到 o2 在它的文档中的位置
                    
                        int _tmp = firstPos.LastIndexOf(",") + 1;
                        int curPos = int.Parse(firstPos.Substring(_tmp, firstPos.Length - _tmp));
                        firstPos = firstPos.Substring(0, _tmp);
                        for (int cpos = 0; cpos < xnl.Count; cpos++) {
                            XmlNode n = getNodeByPosition(o, firstPos + curPos++);
                            xn.Add(n);
                        }*/
                        //Console.WriteLine(xpath + "," + xnl.Count);
                        //Console.WriteLine("=============================================");
                        xn = new List<XmlNode>();
                        _each(_xnl, (o2) =>
                        {
                            //Console.WriteLine(idx++ + "," + xpath + "," + xnl.Count);
                            string pos = _getNodePosition(newXml, o2);
                            xn.Add(_getNodeByPosition(o, pos));

                            return true;
                        });
                    }
                    else
                    {
                        try {
                            if (nsmgr != null)
                                xnl = o.SelectNodes(_makeNSPrefix(xpath), nsmgr);
                            else
                                xnl = o.SelectNodes(xpath);
                        }
                        catch { }
                    }
                }
                if (xnl == null) xnl = o.SelectNodes("/eewfegwqrgwqrgregqwr1234e1341"); //构造一个不存在的节点,避免返回 null;

                return true;
            });

            if (xn != null)
                return xn;
            else
                return xnl;
        }

        private static List<XmlNode> _between(object obj, int n, int m)
        {
            List<XmlNode> lx = new List<XmlNode>();
            int idx = 0;
            _each(obj, (o) =>
            {
                if (idx++ < n)
                    return true;
                lx.Add(o);
                if (idx > m)
                    return false;
                return true;
            });
            return lx;
        }

        private static void _each(object obj, EachHandle2 eachCallBack)
        {
            switch (obj.GetType().Name)
            {
                case "XmlDocument":
                    if (eachCallBack != null)
                    {
                        eachCallBack(((XmlDocument)obj).DocumentElement);
                    }
                    break;
                case "XmlNode":
                case "XmlElement":
                    if (eachCallBack != null)
                    {
                        eachCallBack((XmlNode)obj);
                    }
                    break;
                case "XmlNodeList":
                case "XPathNodeList":
                    foreach (XmlNode n in (XmlNodeList)obj)
                    {
                        if (eachCallBack != null)
                        {
                            if (eachCallBack(n) == false)
                                break;
                        }
                    }
                    break;
                default:
                    if (obj.GetType() == typeof(List<XmlNode>))
                    {
                        foreach (XmlNode n in (List<XmlNode>)obj)
                        {
                            if (eachCallBack != null)
                            {
                                if (eachCallBack(n) == false)
                                    break;
                            }
                        }
                    }
                    else
                    {
                        throw new Exception("XmlOperV2::_each() 未知类型!");
                    }

                    break;
            }
        }

        private static XmlNode _eq(Object obj, int index)
        {
            int _idx = 0;
            XmlNode ret = null;
            _each(obj, (o) =>
            {
                if (_idx++ == index)
                {
                    ret = o;
                    return false;
                }
                return true;
            });
            return ret;
        }

        private static string _text(object obj)
        {
            XmlNode n = _first(obj);
            if (n == null)
                return "";
            return n.InnerText;
        }

        private static string _xml(object obj)
        {
            XmlNode n = _first(obj);
            if (n == null)
                return "";
            return n.InnerXml;
        }

        private static void _xml(object obj, object val)
        {
            _each(obj, (o) =>
            {
                string v = val.ToString().Trim();
                if (v.StartsWith("<![CDATA[") && v.EndsWith("]]>"))
                {
                    var cdata = o.OwnerDocument.CreateCDataSection(v.Substring(9, v.Length - 12));
                    o.InnerXml = "";
                    o.AppendChild(cdata);
                }
                else
                {
                    o.InnerXml = val.ToString();
                }
                return true;
            });
        }

        private static void _text(object obj, object val)
        {
            _each(obj, (o) =>
            {
                o.InnerText = val.ToString();
                return true;
            });
        }

        private static void _append(object obj, XmlNode node)
        {
            _first(obj).AppendChild(node);
        }

        private static XmlNode _first(Object obj)
        {
            return _eq(obj, 0);
        }

        private static void _removeAttr(Object obj, string attName)
        {
            _each(obj, (o) =>
            {
                ((XmlElement)o).RemoveAttribute(attName);
                return true;
            });
        }

        private static string _attr(Object obj, string attName)
        {
            XmlNode n = _first(obj);
            if (n == null)
                return "";
            return ((XmlElement)n).GetAttribute(attName);
        }

        private static void _attr(Object obj, string attName, object val)
        {
            _each(obj, (o) =>
            {
                ((XmlElement)o).SetAttribute(attName, val.ToString());
                return true;
            });
        }


        private static string _getNodePosition(XmlNode anNode, XmlNode cNode)
        {
            string pos = "";

            if (cNode.ParentNode != anNode)
            {
                pos = _getNodePosition(anNode, cNode.ParentNode);
            }

            for (int c = 0; c < cNode.ParentNode.ChildNodes.Count; c++)
            {
                if (cNode.ParentNode.ChildNodes[c] == cNode)
                {
                    pos = pos + "," + c.ToString();
                    if (pos.StartsWith(","))
                    {
                        pos = pos.Remove(0, 1);
                    }
                    return pos;
                }
            }

            return "-1";
        }

        /// <summary>
        /// 在文档中根据位置寻找节点
        /// </summary>
        /// <returns>The node by position.</returns>
        /// <param name="anNode">顶节点</param>
        /// <param name="iLev">需要寻找的深度</param>
        /// <param name="iIdx">需要寻找的索引</param>
        /// <param name="lev">当前深度</param>
        private static XmlNode _getNodeByPosition(XmlNode anNode, string pos)
        {
            string[] spos = pos.Split(‘,‘);
            XmlNode ret = anNode;
            foreach (string idx in spos)
            {
                ret = ret.ChildNodes[int.Parse(idx)];
            }
            return ret;
        }

        private static string _makeXmlTree(string input)
        {
            string[] tags = input.Split(new char[] { ‘/‘ }, StringSplitOptions.RemoveEmptyEntries);
            string xmlStr = "{0}";
            for (int c_tags = 0; c_tags < tags.Length; c_tags++)
            {
                string NodeDesc = tags[c_tags];
                Regex reg = new Regex(@"(\w+)(?:\[([^\]]+)\])?");
                MatchCollection mc = reg.Matches(NodeDesc);
                string strNodes = "";
                foreach (Match m in mc)
                {
                    if (m != null)
                    {
                        string tagName = m.Groups[1].Value;
                        string ext = m.Groups[2].Value;

                        XmlOperV2 xNode = XmlOperV2.load("<${tagName}>{0}</${tagName}>".Replace("${tagName}", tagName));
                        string[] attrs = ext.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                        for (int c_attrs = 0; c_attrs < attrs.Length; c_attrs++)
                        {
                            string attName = attrs[c_attrs].Split(‘=‘)[0];
                            string attValue = attrs[c_attrs].Split(‘=‘)[1];
                            switch (attName)
                            {
                                case "innerText":
                                    xNode.Text(attValue);
                                    break;
                                case "innerXml":
                                    xNode.Xml(attValue);
                                    break;
                                default:
                                    xNode.Attr(attName, attValue);
                                    break;
                            }
                        }

                        strNodes += xNode.OuterXml;
                    }
                }
                xmlStr = string.Format(xmlStr, strNodes);
            }
            return xmlStr.Replace("{0}", "");
        }

        private static string _makeNSPrefix(string xpath)
        {
            Regex reg = new Regex(@"(^|\/)(\w+)(\[|\/|$)");
            xpath = reg.Replace(xpath, @"$1xmlnsDefault:$2$3");
            return xpath;
        }

        private static string[] _getXpathPrefix(string xpath) {
            Regex reg = new Regex(@"(\w*?):\w*");
            MatchCollection mc = reg.Matches(xpath);
            List<string> sRet = new List<string>();
            for (int c = 0; c < mc.Count; c++)
            {
                string prefix = mc[c].Groups[1].Value;
                if (!sRet.Contains(prefix)) {
                    sRet.Add(prefix);
                }
            }
            return sRet.ToArray();
        }

        /// <summary>
        /// 取所有的命名空间
        /// </summary>
        /// <param name="_xmlDoc"></param>
        /// <returns></returns>
        private static XmlNamespaceManager _getNameTable(XmlDocument _xmlDoc, ref List<KeyValuePair<string, string>> lstXmlns)
        {
            XmlNamespaceManager _xnm = null;
            Regex reg = new Regex(@"xmlns\:?(.*?)?=""(.*?)""");
            MatchCollection mc = reg.Matches(_xmlDoc.OuterXml);
            if (mc.Count > 0)
            {
                _xnm = new XmlNamespaceManager(_xmlDoc.NameTable);
                for (int c = 0; c < mc.Count; c++)
                {
                    string n = mc[c].Groups[1].Value;
                    if (n == "")
                        n = "xmlnsDefault";
                    string v = mc[c].Groups[2].Value;

                    lstXmlns.Add(new KeyValuePair<string, string>(n, v));   //记录所有的前缀和命名空间
                    _xnm.AddNamespace(n, v);                                //这个遇到重复的前缀会被覆盖掉
                }
            }
            return _xnm;
        }

        #endregion
    }
}

  

C#.NET 程序员的福利,自己写的一个XML操作类,可实现像jquery一样方便的xml操作,且不用专门去处理命名空间。

标签:star   ret   save   name   定位   class   模糊   命名空间   基础   

原文地址:http://www.cnblogs.com/zhj11226/p/7200241.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!