C# XML的节点遍历、定位、编辑和删除(三)


在项目的实际应用中,有很多数据都会保存为XML配置文件。使用率比较高的操作有加载文档,
读取文档,读取XML的某个节点或属性值,增加或插入一个节点,遍历节点信息等。

XML样例

后面的例子以该xml文档为基础进行演示,在这里我将它放在D:\temp.xml路径下。请注意这个XML文档样例中包含了XmlComment 注释XmlElement 元素,和XmlCDataSection 字符数字段,这些类型同属于节点

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Citys>
  <!--这是一份关于城市省份的文件-->
  <Province level="发达">广东
  <City level="省会">广州</City>
  <City level="一线">深圳</City>
</Province>
  <Province level="发展">广西
    <![CDATA[All Jane Austen novels 25% off starting 3/23!]]>
    <City level="三线">桂林</City>
  </Province>
</Citys>

以下示例演示如何获取根节点,跳转到根节点的第一个子节点、访问其任何子节点、返回到父结点,然后跨同级节点导航。

获取整个文档根开始

演示加载文档,然后使用该对象将文档的内容打印输出到控制台。

            //创建XML文档对象
            XmlDocument document = new XmlDocument();
            //加载整个文档
            document.Load(@"D:\temp.xml");

            //使用document节点将文档内容输出到控制台
            Console.WriteLine(document.DocumentElement.OuterXml);

控制台输出结果:
在这里插入图片描述

获取根节点

演示了如何跳转到根节点的第一个子节点,然后循环访问该节点的子节点。(如果该节点有子节点的话)。

            //创建XML文档对象
            XmlDocument document = new XmlDocument();
            //加载整个文档
            document.Load(@"D:\temp.xml");

            //第一个子节点
            XmlElement root = document.DocumentElement;
          
            if(root.HasChildNodes)
            {//如果有子节点

                 for(int i=0; i<root.ChildNodes.Count; i++)
                {  //展示子节点的内容
                    Console.WriteLine(root.ChildNodes[i].InnerText);
                }
            

示例中root 的值是Citys, 可以从结果中看到该节点下的子节点都会被遍历出来,无论节点类型是XmlElement元素,还是XmlComment注释,或是XmlCDataSection字符数字段。

运行结果:

这是一份关于城市省份的文件
广东广州深圳
广西All Jane Austen novels 25% off starting 3/23!桂林

在这里插入图片描述

获取最后一个子节点

<Province level="发展">广西</Province>是最后一个子节点。

            //创建XML文档对象
            XmlDocument document = new XmlDocument();
            //加载整个文档
            document.Load(@"D:\temp.xml");

            //第一个子节点
            XmlElement root = document.DocumentElement;
          
            if(root.HasChildNodes)
            {//如果有子节点

                XmlNode lastChild = root.LastChild;

                Console.WriteLine("显示最后一个节点元素:");
                Console.WriteLine(lastChild.OuterXml);
            }

运行结果

显示最后一个节点元素:
<Province level="发展">广西<![CDATA[All Jane Austen novels 25% off starting 3/23!]]><City level="三线">桂林</City></Province>

在同级之间向前导航

在xml样例中可以看到注释结点和城市节点City是属于同级节点的。很多情况下我们的xml文件没有添加注释或其它字符数值段,就很容易将它们忽略掉,实际上这些类型也是属于节点。FirstChild使用NextSibling向前导航。

            //创建XML文档对象
            XmlDocument document = new XmlDocument();
            //加载整个文档
            document.Load(@"D:\temp.xml");

            //根节点
            XmlElement root = document.DocumentElement;
          
           //第一个节点
            XmlNode currNode = root.FirstChild;

           Console.WriteLine("显示第一个节点元素:");
           Console.WriteLine(currNode.OuterXml);

            //相邻节点
            XmlNode nextNode = currNode.NextSibling;
            Console.WriteLine("\r\n显示相邻节点元素:");
            Console.WriteLine(nextNode.OuterXml);

运行结果

显示第一个节点元素:
<!--这是一份关于城市省份的文件-->

显示相邻节点元素:
<Province level="发达">广东<City level="省会">广州</City><City level="一线">深圳</City></Province>

在同级之间向后导航

LastChild使用PreviousSibling向后导航。

 //创建XML文档对象
            XmlDocument document = new XmlDocument();
            //加载整个文档
            document.Load(@"D:\temp.xml");

            //根节点
            XmlElement root = document.DocumentElement;
          
           
            XmlNode currNode = root.LastChild;

           Console.WriteLine("显示最后一个节点元素:");
           Console.WriteLine(currNode.OuterXml);


            XmlNode nextNode = currNode.PreviousSibling;
            Console.WriteLine("\r\n显示相邻节点元素:");
            Console.WriteLine(nextNode.OuterXml);

运行结果:

显示最后一个节点元素:
<Province level="发展">广西<![CDATA[All Jane Austen novels 25% off starting 3/23!]]><City level="三线">桂林</City></Province>

显示相邻节点元素:
<Province level="发达">广东<City level="省会">广州</City><City level="一线">深圳</City></Province>

查找节点

可以根据XPath查询字符串来查找一个或多个数据节点。
附录:XPath的表达式MSDN介绍 https://learn.microsoft.com/zh-cn/previous-versions/dotnet/netframework-4.0/ms256086(v=vs.100)?redirectedfrom=MSDN
获取单个节点
演示使用知道节点路径以及是第几个节点来找到省份。

            //创建XML文档对象
            XmlDocument document = new XmlDocument();
            //加载整个文档
            document.Load(@"D:\temp.xml");

            //找Citys元素下的第2个Province元素
            string xPath = "Citys/Province[2]";

            XmlNode currNode = document.SelectSingleNode(xPath);

            if(currNode != null)
            {
                Console.WriteLine("寻找到的元素:");
                Console.WriteLine(currNode.OuterXml);
            }

运行结果

寻找到的元素:
<Province level="发展">广西<![CDATA[All Jane Austen novels 25% off starting 3/23!]]><City level="三线">桂林</City></Province>

还可以使用GetElementById来搜索节点。如果使用这个方法,必须在XML文件的文档类型定义声明中定义ID。
将示例中的XML文档修改如下,此时将Province 节点下的level 声明为ID了。

附录:关于GetElementById的MSDN示例

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!DOCTYPE Citys [  
 
  <!ELEMENT Province ANY>   

  <!ATTLIST Province level ID #REQUIRED>  ]> 

<Citys>
  <!--这是一份关于城市省份的文件-->
  <Province level="发达">广东
  <City level="省会">广州</City>
  <City level="一线">深圳</City>
</Province>
  <Province level="发展">广西
    <![CDATA[All Jane Austen novels 25% off starting 3/23!]]>
    <City level="三线">桂林</City>
  </Province>
</Citys>

使用GetElementById来搜索ID值是发达的节点

            //创建XML文档对象
            XmlDocument document = new XmlDocument();
            //加载整个文档
            document.Load(@"D:\temp.xml");

            //根据(level)ID来搜索节点
            XmlElement findEle = document.GetElementById("发达");
            
            if(findEle != null)
            {                 
                Console.WriteLine("寻找到的元素:");
                Console.WriteLine(findEle.OuterXml);
            }

运行结果:

寻找到的元素:
<Province level="发达">广东
<City level="省会">广州</City><City level="一线">深圳</City></Province>

获取多个节点

在这里使用SelectNodes选择所有Province的节点。

            //创建XML文档对象
            XmlDocument document = new XmlDocument();
            //加载整个文档
            document.Load(@"D:\temp.xml");

            XmlNodeList nodeList;
            //获取根节点
            XmlElement root = document.DocumentElement;

            nodeList = root.SelectNodes("Province");
            foreach(XmlNode node in nodeList)
            {
                //打印节点及其所有子节点的串联值
                Console.WriteLine(node.InnerText);
            }

运行结果:

广东
  广州深圳
广西
    All Jane Austen novels 25% off starting 3/23!桂林

还可以使用GetElementsByTagName通过节点的名称获取节点的集合。

           //创建XML文档对象
            XmlDocument document = new XmlDocument();
            //加载整个文档
            document.Load(@"D:\temp.xml");

            XmlNodeList nodeList;
            //获取根节点
            XmlElement root = document.DocumentElement;

            nodeList = root.GetElementsByTagName("Province");
            foreach(XmlNode node in nodeList)
            {
                //打印节点及其所有子节点的串联值
                Console.WriteLine(node.InnerText);
            }

运行结果同上。

编辑节点

获取某一个(广州)节点,并增加其属性,以及更改原有属性的值。

            //创建XML文档对象
            XmlDocument document = new XmlDocument();
            //加载整个文档
            document.Load(@"D:\temp.xml");

            XmlNodeList nodeList;
            //根节点
            XmlElement root = document.DocumentElement;

            nodeList = root.GetElementsByTagName("City");
            if(nodeList.Count > 0)
            {
                // 获取广州节点
                XmlElement element = (XmlElement) nodeList[0];
                //添加新的属性
                element.SetAttribute("newAttr1", "One");
                element.SetAttribute("newAttr2", "Two");
                element.SetAttribute("newAttr3", "Three");

                //已存在属性的值
                element.Attributes["level"].InnerText = "南方";
              
             }
            document.Save(@"D:\temp.xml");

运行结果:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!DOCTYPE Citys[  
 
  <!ELEMENT Province ANY>   

  <!ATTLIST Province level ID #REQUIRED>  ]>
<Citys>
  <!--这是一份关于城市省份的文件-->
  <Province level="发达">广东
  <City level="南方" newAttr1="One" newAttr2="Two" newAttr3="Three">广州</City>
  <City level="一线">深圳</City></Province>
  <Province level="发展">广西
    <![CDATA[All Jane Austen novels 25% off starting 3/23!]]><City level="省会">桂林</City></Province>
</Citys>

添加节点

可以使用CreateElement方法或CreateNode方法添加节点。
对于任何其他数据类型的节点(比如注释、空格节点或CDATA节点),请使用CreateNode方法。

演示了创建一个省份节点,以及一个城市节点,向这两个节点添加属性,并将节点添加到文档。

             //创建XML文档对象
            XmlDocument document = new XmlDocument();
            //加载整个文档
            document.Load(@"D:\temp.xml");

            //根节点
            XmlElement root = document.DocumentElement;

            //创建省份节点
            XmlElement proEle = document.CreateElement("Province");
            //设置元素值
            proEle.InnerText = "甘肃";
            //设置属性
            proEle.SetAttribute("level", "西北");
            proEle.SetAttribute("Attr5", "测试");

            //创建城市节点
            XmlElement cityEle = document.CreateElement( "City");
            cityEle.InnerText = "兰州";
            cityEle.SetAttribute("level", "拉面");
            //将城市节点添加到省份中
            proEle.AppendChild(cityEle);

            //将省份节点添加到根节点末尾
            root.AppendChild(proEle);

            document.Save(@"D:\temp.xml");

运行结果:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!DOCTYPE Citys[  
 
  <!ELEMENT Province ANY>   

  <!ATTLIST Province level ID #REQUIRED>  ]>
<Citys>
  <!--这是一份关于城市省份的文件-->
  <Province level="发达">广东
  <City level="海南" newAttr1="One" newAttr2="Two" newAttr3="Three">广州</City>
  <City level="一线">深圳</City>
 </Province>

  <Province level="发展">广西
    <![CDATA[All Jane Austen novels 25% off starting 3/23!]]>
    <City level="省会">桂林</City>
  </Province>

  <Province level="西北" Attr5="测试">甘肃
    <City level="拉面">兰州</City>
</Province>
</Citys>

删除节点

使用RemoveChild方法删除节点。

        /// <summary>
        /// 删除一个省份,以及该节点前面出现的空格
        /// </summary>
        /// <param name="province"></param>
        public void DeleteProvince(XmlNode province)
        {
            //前一个节点
            XmlNode preNode = province.PreviousSibling;

            //删除省份节点
            province.OwnerDocument.DocumentElement.RemoveChild(province);

            if(preNode.NodeType == XmlNodeType.Whitespace ||
                preNode.NodeType == XmlNodeType.SignificantWhitespace)
            {//删除空格
                preNode.OwnerDocument.DocumentElement.RemoveChild(preNode);
            }
        }

小结

函数名或类名描述
XmlDocumentXML文档对象
XmlDocument.DocumentElement文档树的根
CreateElement (CreateNode)创建结点
PreviousSibling (NextSibling)同级节点之间的前(后)相邻节点
SelectSingleNode(与XPath配合使用)查找单个节点
GetElementById (与ID配合使用)查找单个节点
SelectNodes(与XPath配合使用)查找多个节点
GetElementsByTagName(与节点名称配合使用)查找多个节点
element.InnerText = "甘肃"; element.SetAttribute("Attr5", "测试")编辑节点
InsertAfter (InsertBefore)定位节点
RemoveChild删除节点

附录参考

1 XPath的使用 XPath的表达式MSDN介绍 https://learn.microsoft.com/zh-cn/previous-versions/dotnet/netframework-4.0/ms256086(v=vs.100)?redirectedfrom=MSDN

2 XML文件的文档类型定义声明中定义ID 关于GetElementById的MSDN示例

3 XmlDocument 类 的介绍 https://learn.microsoft.com/zh-cn/dotnet/api/system.xml.xmldocument?view=net-7.0

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值