C# xml格式化

   最近做项目发现一个问题,c# 向ios传输xml文件时,使用GCDAsync接收数据Data不为空,但是Data转NSString时,为空,最后发现是,传输过程中的数据包含了非utf8格式的字符,然后去网上找了一个xml格式化的工具代码,将xml格式化后再传输就没有问题了,XML格式化代码如下:


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

// 用于实现对xml文件测处理
namespace get_Manifest_txt
{
    /// <summary>
    /// 属性, 形如: encoding="utf-8"
    /// </summary>
    public class attribute
    {
        public string name = "属性名";
        public string value= "属性值";

        public attribute(){}

        /// <summary>
        /// 创建属性
        /// </summary>
        public attribute(string name, string value)
        {
            this.name = name;
            this.value = value;
        }

        /// <summary>
        /// 获取属性,的字符串形式
        /// </summary>
        public string ToString()
        {
            return name + "=" + "\"" + value + "\"";
        }

        /// <summary>
        /// 从属性串创建属性, 形如:encoding="utf-8" 或 encoding=utf-8
        /// </summary>
        public static attribute Parse(string attrStr)
        {
            attrStr = attrStr.Trim();
            if (attrStr.Contains("="))
            {
                attribute iteam = new attribute();
                //string[] A = attrStr.Split('=');          // 按=分割属性名称和属性值
                string[] A = xmlNode.split(attrStr, "=");   // 仅分割为两个字符串
                iteam.name = A[0].Trim();
                iteam.value = A[1].Trim().Trim('"');

                return iteam;
            }
            return null;
        }
    }

    /// <summary>
    /// 属性List, 形如: version="1.0" encoding="utf-8" standalone="no" ...
    /// 包含若干个属性
    /// </summary>
    public class attributeList
    {
        public List<string> list = new List<string>();                             // 属性列表,字符串形式
        public Dictionary<string, string> dic = new Dictionary<string, string>();  // 属性字典,名称、值

        public attributeList() { }


        /// <summary>
        /// 向属性list中添加新的属性
        /// </summary>
        public void Add(attribute attr)
        {
            if (!dic.Keys.Contains(attr.name))
            {
                dic.Add(attr.name, attr.value);
                list.Add(attr.ToString());
            }
        }

        /// <summary>
        /// 向属性list中添加新的属性
        /// </summary>
        public void Add(string name, string value)
        {
            Add(new attribute(name, value));
        }

        /// <summary>
        /// 从属性list中移除指定的属性
        /// </summary>
        public void Remove(attribute attr)
        {
            if (dic.Keys.Contains(attr.name))
            {
                dic.Remove(attr.name);
                list.Remove(attr.ToString());
            }
        }

        /// <summary>
        /// 从属性list中移除指定的属性,name为属性名
        /// </summary>
        public void Remove(string name)
        {
            if (dic.Keys.Contains(name))
                Remove(new attribute(name, dic[name]));
        }

        /// <summary>
        /// 清空属性list
        /// </summary>
        public void Clear()
        {
            list.Clear();
            dic.Clear();
        }

        /// <summary>
        /// 判断属性list中中是否含有属性attr
        /// </summary>
        public bool Contains(attribute attr)
        {
            return list.Contains(attr.ToString());
        }

        /// <summary>
        /// 判断属性list中是否含有属性, name为属性名
        /// </summary>
        public bool Contains(string name)
        {
            return dic.Keys.Contains(name);
        }

        /// <summary>
        /// 判断属性list中是否含有属性值, value为属性值
        /// </summary>
        public bool ContainsValue(string value)
        {
            return dic.Values.Contains(value);

            //foreach (string V in dic.Values)
            //{
            //    if (V.Contains("=\"" + value + "\""))
            //        return true;
            //}
            //return false;
        }

        ///<summary>
        /// 获取属性list的第index个属性
        ///</summary>
        public attribute Get(int index)
        {
            if (index < list.Count) 
                return attribute.Parse(list[index]);
            return null;
        }

        ///<summary>
        /// 获取属性list中,属性名为name的属性值
        ///</summary>
        public string Get(string name)
        {
            if (dic.Keys.Contains(name))
                return dic[name];
            return null;
        }

        /// <summary>
        /// 重新设置属性list中,属性名为name的属性值
        /// 当value为ATTR_NULL时,仅清除节点属性
        /// </summary>
        public void Set(string name, string value)
        {
            Remove(name);           // 移除原有的属性

            if(!value.Equals("ATTR_NULL")) 
                Add(name, value);   // 重新添加新的属性
        }

        /// <summary>
        /// 重新设置属性list中,属性attr
        /// </summary>
        public void Set(attribute attr)
        {
            Remove(attr.name);            // 移除原有的属性
            Add(attr.name, attr.value);   // 重新添加新的属性
        }

        /// <summary>
        /// 重新设置属性List对应的所有属性
        /// </summary>
        public void Set(attributeList List)
        {
            foreach (String name in List.dic.Keys)
            {
                Set(name, List.dic[name]);
            }
        }


        /// <summary>
        /// 获取属性list中的元素数目
        /// </summary>
        public int Count()
        {
            return list.Count;
        }

        /// <summary>
        /// 获取属性list的字符串形式,
        /// 形如:version="1.0" encoding="utf-8" standalone="no"
        /// </summary>
        public string ToString()
        {
            string str = "";

            foreach (string attr in list)
                str += (str.Equals("") ? "" : " ") + attr;

            return str;
        }

        /// <summary>
        /// 获取属性list经排序后的 字符串形式
        /// 形如:version="1.0" encoding="utf-8" standalone="no"
        /// </summary>
        public string SortString()
        {
            attributeList attr = this.Clone();
            attr.list.Sort();       // 元素排序

            return attr.ToString();
        }

        /// <summary>
        /// 从属性串创建属性list, 
        /// 形如:version="1.0" encoding="utf-8" standalone="no"
        /// 或:version=1.0 encoding=utf-8 standalone=no
        /// </summary>
        public static attributeList Parse(string Str)
        {
            if (Str.Contains("="))
            {
                attributeList L = new attributeList();

                //Str = Str.Trim();
                //string[] A = Str.Split('\"');
                //for (int i = 0; i < A.Length-1; i += 2)
                //    L.Add(new attribute(A[i].Trim().Trim('='), A[i + 1]));

                Str = Str.Trim().Replace("\r", " ").Replace("\n", " ").Replace("\t", " ");

                //while (Str.Contains("  ")) Str = Str.Replace("  ", " ");
                //string[] A = Str.Split(' ');
                string[] A = SplitAttrs(Str);

                for (int i = 0; i < A.Length; i ++)
                    L.Add(attribute.Parse(A[i]));

                return L;
            }
            else return new attributeList();
        }

        // 分割属性字符串,如:android:exported="false" android:label="Omlet Network Service" android:name="mobisocial.omlib.service.OmlibService"
        private static string[] SplitAttrs(String attrStr)
        {
            int S = 0, E = 0;
            List<String> list = new List<string>();

            String reminder = attrStr;

            while (reminder.Contains("\""))
            {
                S = reminder.IndexOf("\"");
                E = reminder.IndexOf("\"", S + 1);

                if(E > S)
                {
                    list.Add(reminder.Substring(0, E));
                    reminder = reminder.Substring(E+1).Trim();
                }
            }

            // 非标准形式的属性串,如:package=com.joym.limitkart.baidu 的解析
            reminder = reminder.Trim();
            if (!reminder.Equals(""))
            {
                while (reminder.Contains("  ")) reminder = reminder.Replace("  ", " ");
                string[] A = reminder.Split(' ');
                foreach (String str in A) list.Add(str);
            }

            return list.ToArray();
        }

        /// <summary>
        /// 复制当前attributeList
        /// </summary>
        public attributeList Clone()
        {
            attributeList L = new attributeList();
            foreach (string attr in list)
                L.Add(attribute.Parse(attr));
            return L;
        }

        /// <summary>
        /// 判断两个属性list,是否具有相同的属性;
        /// 是否完全相同根据ToString()后串进行判定
        /// </summary>
        public bool Equals(attributeList attributes)
        {
            if (this != null && attributes != null)
            {
                bool isMin1 = this.Count() <= attributes.Count();
                attributeList min = isMin1 ? this : attributes;
                attributeList max = isMin1 ? attributes : this;

                foreach (string attribute in min.list)
                    if (!max.list.Contains(attribute)) return false;    // 存在不相同的属性
            }

            return true; // 现有属性均相同
        }

        /// <summary>
        /// 创建一个attributeList合集,
        /// 先添加attributes1中的所有属性,再添加仅存在attributes2中的属性
        /// </summary>
        public static attributeList operator +(attributeList attributes1, attributeList attributes2)
        {
            attributeList L = attributes1.Clone();
            foreach (string attr in attributes2.list)
                L.Add(attribute.Parse(attr));
            return L;
        }
    }

    /// <summary>
    /// xml节点
    /// </summary>
    public class xmlNode
    {
        public string name = "节点名";
        public attributeList attributes = new attributeList();  // 节点属性
        public string value = "节点值";
        public List<xmlNode> childs = new List<xmlNode>();      // 子节点
        public bool isDeclarNode = false;                       // 是否为xml的信息声明节点 <?xml version="1.0" encoding="utf-8" standalone="no"?>

        public xmlNode parent;                                  // 父节点
        public Dictionary<string, xmlNode> dic = new Dictionary<string, xmlNode>();    // 子节点特征串, 到子节点的映射表
        public List<string> childNames = new List<string>();    // 存储子节点的节点名列表

        public string note = "";    // 节点的注释说明信息

        /// <summary>
        /// 创建xml节点
        /// </summary>
        public xmlNode() { }

        /// <summary>
        /// 创建xml节点
        /// </summary>
        public xmlNode(string name, attributeList attributes = null, string value = "", List<xmlNode> childs=null) 
        {
            this.name = name;
            if(attributes != null) this.attributes = attributes.Clone();
            this.value = value;
            this.Add(childs);
        }


        /// <summary>
        /// 定义节点的特征串,为名称和节点属性值组合
        /// </summary>
        public string Key()
        {
            string attrs = attributes.ToString();
            return name + (attrs.Equals("") ? "" : " ") + attrs;
        }

        /// <summary>
        /// 定义节点的特征串,为名称和节点属性值组合
        /// </summary>
        public string SortKey()
        {
            string attrs = attributes.SortString();
            return name + (attrs.Equals("") ? "" : " ") + attrs;
        }

        /// <summary>
        /// 获取当前节点在父节点中的路径信息
        /// </summary>
        public string Path()
        {
            if (parent != null) return parent.Path() + "/" + this.name;
            else return this.name;
        }

        /// <summary>
        /// 添加新的子节点到当前节点
        /// </summary>
        public void Add(xmlNode child)
        {
            xmlNode node = child.getSameNode(this); // 在当前节点的子节点中查找与child相似的节点
            if (node == null)
            {
                //添加子节点
                childs.Add(child);
                child.parent = this;

                // 子节点相关信息记录
                if (!dic.Keys.Contains(child.SortKey()))
                    dic.Add(child.SortKey(), child);
                if (!childNames.Contains(child.name))
                    childNames.Add(child.name);
            }
            else
            {
                // 将child节点的属性和其子节点,合并到查找到的相似的子节点中
                node.Combine(child);
            }
        }

        /// <summary>
        /// 添加list的所有节点到当前节点的子节点集合中
        /// </summary>
        public void Add(List<xmlNode> list)
        {
            if (list != null)
            {
                foreach (xmlNode child in list)
                    this.Add(child.Clone());
            }
        }

        /// <summary>
        /// 将节点node的属性和子节点合并到当前节点中
        /// </summary>
        public void Combine(xmlNode node)
        {
            // 添加node中的属性到当前节点中
            this.attributes = this.attributes + node.attributes;

            // 添加node的所有子节点到当前节点中
            this.Add(node.childs);
        }

        /// <summary>
        /// 将两List xmlNode 合并为一个list, 将listSource添加到listTarget上
        /// </summary>
        public static List<xmlNode> Combine(List<xmlNode> listTarget, List<xmlNode> listSource)
        {
            xmlNode N = new xmlNode();
            N.Add(listTarget);
            N.Add(listSource);

            // 清除childs的父节点信息
            foreach (xmlNode child in N.childs)
                child.parent = null;

            return N.childs;
        }


        /// <summary>
        /// 将两个Manifest.xml合并,将listSource添加到listTarget上
        /// 合并"manifest", "application"节点,保留所有activity等待后续操作
        /// </summary>
        public static List<xmlNode> CombineManifest(List<xmlNode> listTarget, List<xmlNode> listSource)
        {
            xmlNode N = new xmlNode();
            N.Add(listTarget);
            N.Add(listSource);

            string[] combinePath = { "manifest", "application"/*, "activity"*/ };
            xmlNode T = N;
            foreach (string name in combinePath)
            {
                // 合并所有manifest到第一个中
                List<xmlNode> list = T.GetChilds(name);
                if (name.Equals("activity"))            
                    list = getLancherActivity(list);    // 获取入口Activity

                for (int i = 1; i < list.Count; i++)
                {
                    if (name.Equals("activity"))        // 移除入口Activity中原有的intent-filter节点
                        list[0].Remove(list[0].Get("intent-filter"));
                        
                    list[0].Combine(list[i]);
                    T.Remove(list[i]);
                }

                T = list[0];
            }

            // 清除childs的父节点信息
            foreach (xmlNode child in N.childs)
                child.parent = null;

            return N.childs;
        }

        /// <summary>
        /// 获取list中,所有节点名为NodeName的节点
        /// 
        /// 如:activity 或 activity:com.game.main
        /// </summary>
        public static List<xmlNode> getNodes(List<xmlNode> list, String NodeName)
        {
            xmlNode N = new xmlNode();
            N.Add(list);
            List<xmlNode> list2 = N.GetChilds(NodeName);

            return list2;
        }

        /// <summary>
        /// 获取所有list中所有入口Activity
        /// </summary>
        public static List<xmlNode> getLancherActivity(List<xmlNode> list)
        {
            List<xmlNode> L = new List<xmlNode>();
            foreach (xmlNode N in list)
                if (N.isLauncherActivity()) L.Add(N);
            return L;
        }

        /// <summary>
        /// 判断当前节点是否是入口Activity
        /// </summary>
        public bool isLauncherActivity()
        {
            if (!this.name.Equals("activity") || !childNames.Contains("intent-filter")) return false;
            else
            {
                xmlNode main = this.Get("intent-filter");
                if (main != null && main.Contains("category android:name=\"android.intent.category.LAUNCHER\""))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// 从当前节点中移除子节点
        /// </summary>
        public void Remove(xmlNode child)
        {
            if (childs == null) childs = new List<xmlNode>();
            if (Contains(child))
            {
                childs.Remove(child);
                child.parent = null;

                dic.Remove(child.SortKey());
            }
        }

        /// <summary>
        /// 判断当前节点中, 是否含有子节点child
        /// </summary>
        public bool Contains(xmlNode child)
        {
            return dic.Keys.Contains(child.SortKey());
        }

        /// <summary>
        /// 判断当前节点中, 是否含有特征串为key的子节点
        /// </summary>
        public bool Contains(string key)
        {
            // 解析Key()串
            string[] A = Parse_Key(key);            
            xmlNode Node = new xmlNode(A[0], attributeList.Parse(A[1]));

            return dic.Keys.Contains(Node.SortKey());
        }

        /// <summary>
        /// 根据子节点的特征串,获取对应的子节点
        /// </summary>
        public xmlNode Get(string key)
        {
            // 解析Key()串
            string[] A = Parse_Key(key);
            xmlNode Node = new xmlNode(A[0], attributeList.Parse(A[1]));
            key = Node.SortKey();

            if (Contains(key)) return dic[key];
            else return null;
        }

        /// <summary>
        /// 根据子节点名,获取节点名对应的所有子节点;
        /// 若节点名为空则获取到的为当前节点
        /// 如:activity 或 activity:com.game.main
        /// </summary>
        public List<xmlNode> GetChilds(string name)
        {
            string[] A = name.Split(':');
            List<xmlNode> L = new List<xmlNode>();
            if (name.Equals("")) L.Add(this);
            else
            {
                if (childNames.Contains(A[0]))
                {
                    foreach (xmlNode child in childs)
                        if (child.name.Equals(A[0])) L.Add(child);
                }

                // 记录所有含有属性值:X的节点
                if (A.Length > 1 && !A[1].Equals(""))
                {
                    List<xmlNode> L2 = new List<xmlNode>();
                    foreach (xmlNode N in L)
                    {
                        if (N.attributes.ContainsValue(A[1]))
                        {
                            L2.Add(N);
                        }
                    }
                    L = L2;
                }
            }

            return L;
        }

        /// <summary>
        /// 根据子节点路径信息获取指定的子节点
        /// 如:获取指定activity下的指定intent-filter节点
        /// manifest/application/activity:com.game.main/intent-filter:lenovoid.MAIN
        /// 
        /// 或者创建 NEWNODE=<action android:name="android.intent.action.MAIN"/>形式的节点
        /// THIS或空串返回当前节点
        /// </summary>
        public xmlNode GetChild_ByPath(string path)
        {
            if (path.StartsWith("NEWNODE") && path.Contains("="))
            {
                String New = path.Substring(path.IndexOf("=") + 1).Trim().Trim('"');
                List<xmlNode> list = xmlNode.Parse(New);
                if (list.Count > 0) return list[0];
            }
            else if (path.Equals("THIS")) return this;

            xmlNode N = this;
            string[] A = path.Split('/');
            foreach (string P in A)
            {
                List<xmlNode> L = N.GetChilds(P);
                if (L.Count > 0) N = L[0];
                else return null;
            }

            return N;
        }

        /// <summary>
        /// 合并节点, sourcePath到targetPath的子节点;
        /// 添加source节点的属性和子节点到target节点,若target已有某条属性则不变,没有则添加
        /// 
        /// 或添加节点sourcePath到targetPath, targetPath需以"/CHILDS"结尾
        /// </summary>
        public void Add(string sourcePath, string targetPath)
        {
            xmlNode source = this.GetChild_ByPath(sourcePath);
            bool addchils = targetPath.EndsWith("/CHILDS");
            if(addchils)
            {
                targetPath = targetPath.Substring(0, targetPath.LastIndexOf("/CHILDS"));
            }

            xmlNode target = this.GetChild_ByPath(targetPath);
            if (source == null || target == null) return;

            // 添加source节点的属性和子节点到target节点
            if (addchils) target.childs.Add(source);
            else target.Combine(source);
        }

        /// <summary>
        /// 替换节点,
        /// 添加source节点的属性和子节点到target节点,若target已有某条属性则不变,没有则添加
        /// </summary>
        public void Replace(string targetPath, string sourcePath)
        {
            xmlNode source = this.GetChild_ByPath(sourcePath);
            xmlNode target = this.GetChild_ByPath(targetPath);
            if (source == null || target == null) return;

            // 替换节点
            xmlNode parent = target.parent;
            if (parent != null)
            {
                parent.Remove(target);
                parent.Add(source.Clone());
            }
        }

        /// <summary>
        /// 设置path对应节点的属性值为attributeStr或attributeListStr
        /// 形如:version="1.0" encoding="utf-8" standalone="no"
        /// 或:version=1.0 encoding=utf-8 standalone=no
        /// </summary>
        public void SetAttribute(string path, string attributeStr)
        {
            xmlNode N = this.GetChild_ByPath(path);
            attributeList attrs = attributeList.Parse(attributeStr);
            if (N != null && attrs != null) N.attributes.Set(attrs);
        }

        /// <summary>
        /// 删除节点, nodePath对应的节点
        /// 或者删除nodePath的所有子节点,nodePath需以/CHILDS结尾
        /// </summary>
        public void Remove(string nodePath)
        {
            bool removeChils = nodePath.EndsWith("/CHILDS");
            if (nodePath.EndsWith("/CHILDS")) 
                nodePath = nodePath.Substring(0, nodePath.LastIndexOf("/CHILDS"));

            xmlNode node = this.GetChild_ByPath(nodePath);
            if (node != null)
            {
                if (removeChils) node.childs.Clear();
                else
                {
                    if (node.parent != null) node.parent.Remove(node);
                }
            }
        }


        /// <summary>
        /// 判断当前节点和node,是否为具有相同名称 和 属性list
        /// </summary>
        public bool Equals(xmlNode node)
        {
            if (this == null || node == null) return false;
            if (!this.name.Equals(node.name)) return false;       // 名称不相同
            if (!this.attributes.Equals(node.attributes)) return false; // 属性不相同
            return true;
        }

        /// <summary>
        /// 获取root的子节点中,与当前节点具有相同名称和属性的节点
        /// 重合的节点属性均相同,但Key()可能不同
        /// </summary>
        public xmlNode getSameNode(xmlNode root)
        {
            if (root != null)
            {
                if (this.attributes.Count() == 0 && this.childs.Count == 0 && !this.value.Equals("")) 
                    return null;    // 没有属性,没有子节点,仅有value值时,视作没有相同节点
                else
                {
                    if (root.dic.Keys.Contains(SortKey()))
                        return root.dic[SortKey()];

                    foreach (xmlNode child in root.childs)
                        if (child.Equals(this)) return child;
                }
            }

            return null;
        }

        /// <summary>
        /// 从当前节点复制出一个新的节点
        /// </summary>
        public xmlNode Clone()
        {
            xmlNode N = new xmlNode();
            N.name = this.name;
            N.value = this.value;
            N.attributes = this.attributes.Clone();
            N.Add(this.childs);
            N.isDeclarNode = this.isDeclarNode;

            N.note = this.note;

            return N;
        }

        /// <summary>
        /// 定义xmlNode合并逻辑,从node1、和node2创建一个新的节点
        /// </summary>
        public static xmlNode operator +(xmlNode node1, xmlNode node2)
        {
            xmlNode N = node1.Clone();
            N.Combine(node2);

            return N;
        }

        /// <summary>
        /// 获取当前xmlNode的层次信息,检索parent直到为null的次数
        /// </summary>
        public int Layer()
        {
            int i = 0;
            xmlNode N = this;
            while (N.parent != null)
            {
                N = N.parent;
                i++;
            }
            return i;
        }

        /// <summary>
        /// 获取当前节点的输出为字符串时,需要缩进的空格数
        /// </summary>
        private string Space()
        {
            int layer = Layer();
            string tabs = "";
            while (layer-- > 0) tabs += "    ";  // tabs += "\t";

            return tabs;
        }

        /// <summary>
        /// 定义xmlNode的字符串形式
        /// </summary>
        public string ToString()
        {
            // 是否为xml声明信息
            if (isDeclarNode) return "<?" + Key() + "?>";

            string space = Space();
            string str = space + "<" + Key();

            // 有子节点时的显示样式
            if (childs.Count > 0)
            {
                str += ">";
                foreach (xmlNode child in childs)
                    str += "\r\n" + child.ToString();
                str += "\r\n" + space + "</" + name + ">";
            }
            // 有值时的显示样式
            else if (!value.Equals(""))
            {
                str += ">" + value + "</" + name + ">";
            }
            // 其余显示样式
            else str += "/>";

            // 添加当前节点的注释信息
            if (!note.Equals("")) str = space + note + "\r\n" + str;

            return str;
        }

        /// <summary>
        /// 转化list为字符串形式
        /// </summary>
        public static string ToString(List<xmlNode> list)
        {
            string Str = "";

            bool haveDeclar = false;
            foreach (xmlNode node in list)
            {
                Str += (Str.Equals("") ? "" : "\r\n") + node.ToString();
                if (node.isDeclarNode == true) haveDeclar = true;
            }

            string declar = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n";
            Str = (!haveDeclar ? declar : "") + Str;

            return Str;
        }

        /// <summary>
        /// 从字符串形式的xml节点,构建xmlNode
        /// </summary>
        public static xmlNode ParseOne(string Str)
        {
            List<xmlNode> L = Parse(Str);
            if (L.Count > 0) return L[0];
            else return null;
        }

        /// <summary>
        /// 从字符串形式的xml节点,构建xmlNode
        /// </summary>
        public static List<xmlNode> Parse(string Str)
        {
            List<xmlNode> list = new List<xmlNode>();
            string reminds = "";

            string noteInfo = "";
            while (!(Str = Str.Trim()).Equals(""))
            {
                try
                {
                    int S = Str.IndexOf("<") + 1, E = Str.IndexOf(">", S);
                    String key = Str.Substring(S, E - S);
                    reminds = Str.Substring(E + 1);         // 记录剩余未解析的串

                    // 注释信息不解析
                    if (key.StartsWith("!--"))
                    {
                        E = Str.IndexOf("-->", S);
                        S = S - 1;

                        // 获取节点注释信息
                        noteInfo = Str.Substring(S, E - S + "-->".Length);

                        // 剔除注释信息
                        Str = Str.Substring(E + "-->".Length);
                        continue;
                    }

                    bool isDeclear = key.StartsWith("?");   // 判定是否为xml声明节点
                    if (isDeclear) key = key.Trim('?');

                    string[] A = Parse_Key(key);            // 解析Key()串

                    // 创建xmlNode对象
                    xmlNode Node = new xmlNode(A[0], attributeList.Parse(A[1]));
                    Node.isDeclarNode = isDeclear;

                    bool haveChildValue = (!isDeclear && !key.EndsWith("/"));  // 判断是否有子节点或值
                    if (haveChildValue)
                    {
                        //int E2 = Str.IndexOf("</" + A[0], E);
                        int E2 = getMatchIndex(Str, A[0]);      // 获取与A[0]匹配的/A[0]在Str中的索引位置
                        string ValueStr = Str.Substring(E + 1, E2 - E - 1);

                        E2 = Str.IndexOf(">", E2 + 1);
                        reminds = Str.Substring(E2 + 1);        // 记录剩余未解析的串

                        // 含有子节点,进行子节点的解析
                        //if (ValueStr.StartsWith("\"") && ValueStr.EndsWith("\"")) Node.value = ValueStr;    // 以引号开头和结尾的为节点值
                        //else
                        {
                            String ValueStrTmp = ValueStr.Trim();
                            if (ValueStrTmp.StartsWith("<") && ValueStrTmp.EndsWith(">") && ValueStrTmp.Contains("/"))
                            {
                                List<xmlNode> childs = Parse(ValueStr);
                                Node.Add(childs);
                            }
                            // 有节点值 
                            else Node.value = ValueStr;
                        }
                    }

                    // 为当前节点添加注释信息
                    if (!noteInfo.Equals(""))
                    {
                        Node.note = noteInfo;
                        noteInfo = "";
                    }

                    list.Add(Node);

                    Str = reminds;
                }
                catch (Exception ex)
                {
                    DialogResult result = MessageBox.Show("解析" + Str + "时异常!", "是否查看?", MessageBoxButtons.OKCancel);
                    if (result == DialogResult.OK)
                    {
                        String path = AppDomain.CurrentDomain.BaseDirectory + "xmlNode解析异常.txt";
                        if (File.Exists(path)) File.Delete(path);
                        FileProcess.SaveProcess(Str, path);
                        System.Diagnostics.Process.Start(path);
                    }

                    break;
                }
            }

            return list;
        }

        //<LinearLayout>
        //    <RelativeLayout>ssss3</RelativeLayout>
        //    <LinearLayout >ssss1</LinearLayout>
        //    <LinearLayout>ssss2</LinearLayout>
        //    <LinearLayout><TextView/></LinearLayout>
        //</LinearLayout>

        // 获取与首个<key >匹配的</key >索引位置
        private static int getMatchIndex(string data, string key)
        {
            int index = -1;
            int pos = 0;
            string keyStr = "";
            int count = 0;

            do
            {
                keyStr = getKeyStr(data, key, pos);     // <key > 或 </key >对应串
                index = data.IndexOf(keyStr, pos);      // 获取索引位置
                pos = index + keyStr.Length;            // 记录检索位置

                if (keyStr.StartsWith("</")) count--;
                else if (keyStr.StartsWith("<") && !keyStr.EndsWith("/>")) count++; // 累计匹配值

                if (keyStr.Equals("")) return -1;

            } while (count != 0);

            string reminds = data.Substring(index, data.Length - index);

            return index;
        }

        // 从坐标S0处开始,获取<key > 或 </key >标识的串
        private static string getKeyStr(string data, string key, int S0)
        {
            string str = getNodeString(data, key, S0);          // 获取<key >节点串

            string str2 = getNodeString(data, "/" + key, S0);   // 获取</key >节点串
            if (!str2.Equals(""))
            {
                if (str.Equals("")) str = str2;
                else
                {
                    int index1 = data.IndexOf(str, S0);
                    int index2 = data.IndexOf(str2, S0);

                    if (index2 < index1) str = str2;            // 取<key >或</key >靠前的那个
                }
            }
            return str;
        }

        // 从data中获取第一个以<key ***>标识的串
        private static string getNodeString(string data, string key, int S0)
        {
            if (data.Contains("<" + key) && data.Contains(">"))
            {
                int S = data.IndexOf("<" + key, S0);
                if (S != -1)
                {
                    int E = data.IndexOf(">", S + key.Length + 1);
                    if (E > S) return data.Substring(S, E - S + 1);
                }
            }
            return "";
        }

        /// <summary>
        /// 解析Key()串, 形如:xml encoding="utf-8"
        /// </summary>
        private static string[] Parse_Key(string key)
        {
            string key0 = key.Trim().Trim('/');
            key = key0.Replace("\r", " ").Replace("\t", " ").Replace("\n", " ");
            int S = key.IndexOf(" ");
            if (S == -1) return new string[] { key0, "" };
            else
            {
                string name = key.Substring(0, S);
                string attrs = key.Substring(S + 1).Trim();

                return new string[] { name, attrs };
            }
        }

        /// <summary>
        /// 判断node1和node2,是否完全相同
        /// 具有相同的节点名、节点属性、节点属性、子节点
        /// </summary>
        //public static bool Equals(xmlNode node1, xmlNode node2)
        //{
        //    if (node1 != node2) return false;

        //}


        /// <summary>
        /// 将两个xml文件,按节点属性名自动合并为同一个xml
        /// </summary>
        public static List<xmlNode> Combine(string xmlSource, string xmlTarget, bool isManifest)
        {
            List<xmlNode> listTarget = xmlNode.Parse(xmlTarget);
            List<xmlNode> listSource = xmlNode.Parse(xmlSource);

            List<xmlNode> list = !isManifest ? xmlNode.Combine(listTarget, listSource) : xmlNode.CombineManifest(listTarget, listSource);
            return list;

            //string xml = xmlNode.ToString(list);
            //return xml;
        }


        /// <summary>
        /// 获取manifests中的包名信息, manifest_File为 AndroidManifest.xml文件的完整路径
        /// </summary>
        public static string getPackageName(string manifest_File)
        {
            string xmlTarget = FileProcess.fileToString(manifest_File);
            if (xmlTarget.Equals("")) return "";

            List<xmlNode> listTarget = xmlNode.Parse(xmlTarget);
            List<xmlNode> gameManifests = getNodes(listTarget, "manifest");     // 获取manifest节点
            String packageName = getPackageName(gameManifests);                 // 获取游戏包名信息
            return packageName;
        }

        // 获取manifests中的包名信息
        private static string getPackageName(List<xmlNode> manifests)
        {
            if(manifests.Count > 0 )
            {
                xmlNode manifest = manifests[0];
                attributeList attrs = manifest.attributes;
                if(attrs != null && attrs.Contains("package"))
                    return attrs.Get("package");
            }
            return "";
        }

        /// <summary>
        /// 从文件中载入xml文件, 先复制FileTarget,在添加FileSource,输出到outFile
        /// </summary>
        public static void Combine(string FileSource, string FileTarget, string outFile, bool isManifest, List<string> cmds)
        {
            string xmlTarget = FileProcess.fileToString(FileTarget);
            string xmlSource = FileProcess.fileToString(FileSource);

            //string xml = xmlNode.Combine(xml1, xml2, isManifest);
            //FileProcess.SaveProcess(xml, outFile);

            List<xmlNode> list = xmlNode.Combine(xmlSource, xmlTarget, isManifest);   // 执行Manifest简单混合

            string xml = xmlNode.ToString(list);
            FileProcess.SaveProcess(xml, outFile);                          // 保存文件

            //Manifest manifest = new Manifest(list, outFile);                // 创建Manifest对象

            ////FileProcess.SaveProcess(xmlNode.ToString(list), outFile.Replace(".xml", "_缓存.xml"));

            //// 执行manifest修改逻辑
            ////string[] cmd = { "remove GAME_MAIN_ACTIVITY/intent-filter", "add THIS_MAIN_ACTIVITY to GAME_MAIN_ACTIVITY" };   // 执行操作移除游戏入口Activity中的intent-filter,混合附加入口Activity
            ////string[] cmd = { "remove GAME_MAIN_ACTIVITY/intent-filter", "add activity:com.ltsdk_entryDemo.LogoActivity to GAME_MAIN_ACTIVITY", "remove activity:com.ltsdk_entryDemo.LogoActivity" };
            //if (isManifest)
            //{
            //    // 执行manifest处理逻辑
            //    manifest.runCMD(cmds);

            //    // 获取游戏图标名称,如: @drawable/icon
            //    Settings.gameIcon = manifest.icon;
            //}

            //// 保存manifest
            //manifest.save();
        }




        //// 自定义cmd处理命令逻辑

        /// <summary>
        /// 执行多条操作
        /// </summary>
        public void runCMD(List<string> cmds)
        {
            if (cmds != null && cmds.Count > 0) runCMD(cmds.ToArray());
        }

        /// <summary>
        /// 执行多条操作
        /// </summary>
        public void runCMD(string[] cmds)
        {
            foreach (string cmd in cmds)
            {
                try
                {
                    runCMD(cmd);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(Path() + ".runCMD()报错:" + cmd + "\r\n" + ex.Message);
                }
            }
        }

        /// <summary>
        /// 自定Manifest处理逻辑
        /// path (形如 manifest/application/activity:com.shjc.jsbc.Main),也可定义path为创建新的节点,NEWNODE=<action android:name="android.intent.action.MAIN"/>
        /// add path1 to path2      (添加path1对应的节点信息到path2)
        /// replace path1 by path2  ()
        /// remove path             (删除path处的节点)
        /// get path set attr       (获取指定的节点,并修改其属性值attr)
        /// GAME_MAIN_ACTIVITY      (指代游戏入口Activity Path)
        /// THIS_MAIN_ACTIVITY      (指代当前配置计费包apk的Activity Path)
        /// </summary>
        public void runCMD(string cmd)
        {
            // 移除指定的节点
            if (cmd.StartsWith("remove "))
            {
                string path = cmd.Substring("remove ".Length);
                Remove(path);
            }
            else if (cmd.StartsWith("get "))
            {
                cmd = cmd.Substring("get ".Length).Trim();

                string[] A = split(cmd, " set ");
                if (A.Length > 1) SetAttribute(A[0], A[1]);
            }
            else if (cmd.StartsWith("add "))
            {
                cmd = cmd.Substring("add ".Length).Trim();

                string[] A = split(cmd, " to ");
                if (A.Length > 1) Add(A[0], A[1]);
            }
            else if (cmd.StartsWith("replace "))
            {
                cmd = cmd.Substring("replace ".Length).Trim();

                string[] A = split(cmd, " by ");
                if (A.Length > 1) Replace(A[0], A[1]);
            }
        }

        /// <summary>
        /// 将data按seprator分割为两个子串
        /// </summary>
        public static string[] split(string data, string seprator)
        {
            if (data.Contains(seprator))
            {
                int S = data.IndexOf(seprator), E = S + seprator.Length;
                string[] A = new string[2];
                A[0] = data.Substring(0, S).Trim();
                A[1] = data.Substring(E).Trim();

                return A;
            }
            else return new string[] { data };
        }
    }

    /// <summary>
    /// 定义Manifest用于修改Manifest.xml
    /// </summary>
    public class Manifest
    {
        //public static Cmd.Callback call;

        // 基础数据
        string filePath = "";
        public List<xmlNode> list;

        // 拓展信息
        public xmlNode manifest;
        public xmlNode application;
        public xmlNode LauncherActivity;// 启动Activity
        public string applicationName;  // 应用包名
        public string icon;             // icon图标属性值

        List<xmlNode> permissions;
        List<xmlNode> activitys;
        List<xmlNode> services;
        List<xmlNode> meta_datas;
        List<xmlNode> receivers;

        string GAME_MAIN_ACTIVITY;  // 指代Manifest.xml第一个MAIN_ACTIVITY路径
        string THIS_MAIN_ACTIVITY;  // 指代Manifest.xml第二个MAIN_ACTIVITY路径
        string MANIFEST = " ";      // 指代manifest节点


        Dictionary<string, xmlNode> ActivityDic = new Dictionary<string, xmlNode>();

        public Manifest(string filePath)
        {
            this.filePath = filePath;
            string xml = FileProcess.fileToString(filePath);
            list = xmlNode.Parse(xml);

            InitLoad();
        }

        public Manifest(string xml, string filePath)
        {
            this.filePath = filePath;
            list = xmlNode.Parse(xml);

            InitLoad();
        }


        public Manifest(List<xmlNode> list, string filePath)
        {
            this.filePath = filePath;
            this.list = list;
            InitLoad();
        }

        /// <summary>
        /// 初始载入,预处理
        /// </summary>
        private void InitLoad()
        {
            if (!(list.Count > 1 || !list[1].name.Equals("manifest"))) return;
            manifest = list[1];

            List<xmlNode> L = manifest.GetChilds("application");
            if (L.Count == 0) return;
            application = L[0];

            permissions = manifest.GetChilds("uses-permission");

            if (application == null) return;
            activitys = application.GetChilds("activity");
            services = application.GetChilds("service");
            meta_datas = application.GetChilds("meta-data");
            receivers = application.GetChilds("receiver");

            if (application.attributes != null)
            {
                applicationName = application.attributes.Get("android:name");
                icon = application.attributes.Get("android:icon");
            }


            // 获取activitys中所有入口Activity
            L = xmlNode.getLancherActivity(activitys);
            if (L.Count == 0) return;
            LauncherActivity = L[0];

            // 获取第一个入口Activity路径
            string name1 = L[0].attributes.Get("android:name");
            GAME_MAIN_ACTIVITY = "activity:" + name1;

            if (L.Count > 1)
            {
                // 获取第一个入口Activity路径
                string name2 = L[1].attributes.Get("android:name");
                THIS_MAIN_ACTIVITY = "activity:" + name2;
            }
            else THIS_MAIN_ACTIVITY = "";
        }

        /// <summary>
        /// 已Activity的名称为键值,构建映射表
        /// </summary>
        private void createDic(List<xmlNode> activitys)
        {
            //<activity android:name="com.shjc.jsbc.view2d.selectmap.SelectMap" android:screenOrientation="landscape"/>
            foreach (xmlNode N in activitys)
            {
                if (N.attributes != null)
                {
                    string activityName = N.attributes.Get("android:name");
                    if(!ActivityDic.Keys.Contains(activityName))
                        ActivityDic.Add(activityName, N);
                }
            }
        }

        /// <summary>
        /// 保存到文件
        /// </summary>
        public void save()
        {
            string xml = xmlNode.ToString(list);
            FileProcess.SaveProcess(xml, filePath);
        }

        /// <summary>
        /// 设置应用包名
        /// </summary>
        public void setApplicationName(string name)
        {
            if (application != null || application.attributes != null)
            {
                application.attributes.Set("android:name", name);
            }
        }

        /// <summary>
        /// 获取对应名称的Activity节点, 如:com.shjc.jsbc.Main
        /// </summary>
        public xmlNode getActivity(string name)
        {
            if (ActivityDic.Keys.Contains(name))
                return ActivityDic[name];
            else return null;
        }

        /// <summary>
        /// 根节点manifest
        /// 获取path对应的节点
        /// 
        /// 如: 
        /// uses-permission:android.permission.SEND_SMS
        /// 
        /// application/activity:com.shjc.jsbc.Main 或
        /// activity:com.shjc.jsbc.Main
        /// service:com.lenovo.AppCheckService
        /// meta-data:lenovo.gamesdk.new
        /// receiver:com.lenovo.lsf.push.receiver.PushReceiver
        /// </summary>
        private string FullPath(string path)
        {
            if (path.Contains("GAME_MAIN_ACTIVITY")) path = path.Replace("GAME_MAIN_ACTIVITY", GAME_MAIN_ACTIVITY);    // 替换字段为游戏入口Activity路径
            if (path.Contains("THIS_MAIN_ACTIVITY")) path = path.Replace("THIS_MAIN_ACTIVITY", THIS_MAIN_ACTIVITY);    // 计费包入口Activity路径
            if (path.Contains("MANIFEST")) path = path.Replace("MANIFEST", MANIFEST);
            
            path = path.Trim();
            if (path.StartsWith("activity:") || path.StartsWith("service:") || path.StartsWith("meta-data:") || path.StartsWith("receiver:"))
                path = "application/" + path;

            return path.Trim();
        }

        /// <summary>
        /// 执行多条操作
        /// </summary>
        public void runCMD(List<string> cmds)
        {
            if(cmds != null && cmds.Count > 0) runCMD(cmds.ToArray());
        }

        /// <summary>
        /// 执行多条操作
        /// </summary>
        public void runCMD(string[] cmds)
        {
            foreach (string cmd in cmds)
            {
                try
                {
                    runCMD(cmd);
                }
                catch (Exception ex) 
                {
                    //if (call != null && !cmd.Equals("")) call("【E】" + "Manifest.runCMD()报错:" + cmd + "\r\n" + ex.Message);
                }
            }
        }

        /// <summary>
        /// 自定Manifest处理逻辑
        /// path (形如 manifest/application/activity:com.shjc.jsbc.Main),也可定义path为创建新的节点,NEWNODE=<action android:name="android.intent.action.MAIN"/>
        /// add path1 to path2      (添加path1对应的节点信息到path2)
        /// replace path1 by path2  ()
        /// remove path             (删除path处的节点)
        /// get path set attr       (获取指定的节点,并修改其属性值attr)
        /// GAME_MAIN_ACTIVITY      (指代游戏入口Activity Path)
        /// THIS_MAIN_ACTIVITY      (指代当前配置计费包apk的Activity Path)
        /// </summary>
        public void runCMD(string cmd)
        {
            //if (call != null && !cmd.Equals("")) call("【I2】" + cmd);
            if (cmd.Contains("THIS_MAIN_ACTIVITY") && THIS_MAIN_ACTIVITY.Equals("")) return;
            if (THIS_MAIN_ACTIVITY.Equals("") && cmd.Equals("remove GAME_MAIN_ACTIVITY/intent-filter")) return;     // 当渠道入口为空时,不移除游戏入口中的intent-filter

            // 移除指定的节点
            if(cmd.StartsWith("remove "))
            {
                string path = FullPath(cmd.Substring("remove ".Length));
                manifest.Remove(path);
            }
            else if(cmd.StartsWith("get "))
            {
                cmd = cmd.Substring("get ".Length).Trim();

                string[] A = split(cmd, " set ");
                if (A.Length > 1) manifest.SetAttribute(FullPath(A[0]), A[1]);
            }
            else if (cmd.StartsWith("add "))
            {
                cmd = cmd.Substring("add ".Length).Trim();
                
                string[] A = split(cmd, " to ");
                if (A.Length > 1) manifest.Add(FullPath(A[0]), FullPath(A[1]));
            }
            else if (cmd.StartsWith("replace "))
            {
                cmd = cmd.Substring("replace ".Length).Trim();

                string[] A = split(cmd, " by ");
                if(A.Length > 1) manifest.Replace(FullPath(A[0]), FullPath(A[1]));
            }
        }

        /// <summary>
        /// 将data按seprator分割为两个子串
        /// </summary>
        public static string[] split(string data, string seprator)
        {
            if (data.Contains(seprator))
            {
                int S = data.IndexOf(seprator), E = S + seprator.Length;
                string[] A = new string[2];
                A[0] = data.Substring(0, S).Trim();
                A[1] = data.Substring(E).Trim();

                return A;
            }
            else return new string[] { data };
        }
    }


    public class FileProcess
    {
        #region 文件读取与保存

        /// <summary>
        /// 获取文件中的数据串
        /// </summary>
        public static string fileToString(String filePath)
        {
            string str = "";

            //获取文件内容
            if (System.IO.File.Exists(filePath))
            {
                bool defaultEncoding = filePath.EndsWith(".txt");

                System.IO.StreamReader file1;

                file1 = new System.IO.StreamReader(filePath);                  //读取文件中的数据
                //if (defaultEncoding) file1 = new System.IO.StreamReader(filePath, Encoding.Default);//读取文件中的数据
                //else file1 = new System.IO.StreamReader(filePath);                  //读取文件中的数据

                str = file1.ReadToEnd();                                            //读取文件中的全部数据

                file1.Close();
                file1.Dispose();
            }
            return str;
        }

        /// <summary>
        /// 保存数据data到文件处理过程,返回值为保存的文件名
        /// </summary>
        public static String SaveProcess(String data, String filePath, Encoding encoding = null)
        {
            //不存在该文件时先创建
            System.IO.StreamWriter file1 = null;
            if (encoding == null) file1 = new System.IO.StreamWriter(filePath, false/*, System.Text.Encoding.UTF8*/);     //文件已覆盖方式添加内容
            else file1 = new System.IO.StreamWriter(filePath, false, Encoding.Default);     // 使用指定的格式进行保存

            file1.Write(data);                                                              //保存数据到文件

            file1.Close();                                                                  //关闭文件
            file1.Dispose();                                                                //释放对象

            return filePath;
        }

        /// <summary>
        /// 获取当前运行目录
        /// </summary>
        public static string CurDir()
        {
            return AppDomain.CurrentDomain.BaseDirectory;
        }

        #endregion
    }

}


调用方法:

Manifest manifesetFile = new Manifest(XmlFilePath);
manifesetFile.save();

原文博客: https://blog.csdn.net/scimence/article/details/52807553

猜你喜欢

转载自blog.csdn.net/taoerit/article/details/81301957