CH11-操作XML文件

本章目标

  1. 认识XML文件
  2. 会编写XML文件
  3. 通过C#操作XML文件
  4. 通过C#和XML文件完成相应程序

本章内容

1、XML概述:

  1. XML的概念:

    XML(Extensible Markup Language)是一种用于存储和传输数据的标记语言。它由万维网联盟(W3C)开发。
    XML被广泛用于数据交换、数据存储、Web服务、网络协议(如SOAP)等方面。它是一种非常流行的数据格式,在Web开发中扮演着重要角色。
    XML与HTML类似,但XML更加灵活和可扩展,它允许开发人员创建自己的标记,而不是只限于HTML中预定义的标记。

  2. XML的特点:

    • 可扩展性:XML允许开发人员创建自定义的标记和元素,以表示数据和结构,这使得XML可以用于多种应用程序和领域。
    • 结构化:XML文档由嵌套的元素和属性组成,这使得XML可以表示复杂的数据结构。
    • 标准化:XML支持标准化的字符编码,如UTF-8和UTF-16,这使得XML可以在不同的平台和应用程序之间进行交换和处理。
    • 简单易读:XML文档具有清晰的层次结构和良好的可读性,这使得XML易于编写和理解。

2、XML的基本结构

  1. XML声明:

    每个XML文档都必须包含一个声明,它描述了XML文档的版本和编码方式。例如,在以下的XML文档中,声明了XML版本1.0,编码方式为UTF-8

    1
    <?xml version="1.0" encoding="UTF-8"?>
  2. 根元素:

    XML文档必须有一个根元素,它包含了所有其他元素。根元素通常是所有其他元素的父元素。例如,在以下的XML文档中,是根元素。

    1
    2
    3
    <person>  
    <!-- 其他元素 -->
    </person>
  3. 元素

    元素是XML文档的基本单位,它包含文本或其他元素。元素通过标签来标识,例如,以下的XML文档中,是段落元素的开始和结束标签

    1
    2
    3
    <person>  
    <student>这是一个学生</student>
    </person>
  4. 属性

    属性是元素的附加信息,它们提供了关于元素的额外信息。属性在开始标签中定义,并以名称/值对的形式出现。例如,以下的XML文档中,name是student元素的属性,值为”张三”;age是student元素的另一个属性,值为18:

    1
    2
    3
    <person>  
    <student name="张三" age=18>这是一个学生</student>
    </person>
  5. 注释

    注释用于在XML文档中添加注释和说明。注释以结束。例如,以下的XML文档中,是一个注释:

    1
    <!-- 这是一个注释 -->
  6. 命名空间:

    一个用于定义XML文档中元素和属性的范围和作用域的机制。它允许在XML文档中定义多个不同的命名空间,以便将元素和属性限制在特定的范围内。

    在XML中,命名空间被定义为一个URI(统一资源标识符),它为XML元素提供一个唯一的名称。命名空间可以用于区分具有相同名称的元素或属性,使用命名空间可以帮助避免名称冲突。

    在XML文档中,命名空间可以用以下两种方式定义:

    1. 在元素上定义命名空间:可以在XML文档的根元素或特定元素上使用命名空间属性来定义命名空间。例如:

      1
      2
      3
      <root>  
      <element xmlns="http://example.com/"></element>
      </root>
    2. 使用XML命名空间前缀:可以使用XML命名空间前缀来定义命名空间,并指定其URI。例如:

      1
      2
      3
      <root xmlns:ns="http://www.example.com">  
      <ns:element>Value</ns:element>
      </root>
    3. 多个命名空间:

      1
      2
      3
      4
      5
      6
      <?xml version="1.0" encoding="UTF-8"?>  
      <root xmlns:ns1="http://www.example.com/namespace1"
      xmlns:ns2="http://www.example.com/namespace2">
      <ns1:element1>Value 1</ns1:element1>
      <ns2:element2>Value 2</ns2:element2>
      </root>
  7. 一个完整的XML文件实例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?xml version="1.0" encoding="utf-8" ?>
    <person>
    <!--学生1-->
    <student studentNo="1001">
    <name>张三</name>
    <age>18</age>
    <gender></gender>
    </student>
    <!--学生2-->
    <student studentNo="1002">
    <name>张三</name>
    <age>18</age>
    <gender></gender>
    </student>
    </person>

3、C#创建XML文件

  1. 对象及方法说明:

    1. XmlDocument:是.NET框架中用于表示整个XML文档的对象

      1
      2
      //1.创建一个新的XML文档对象
      XmlDocument xmlDoc = new XmlDocument();
    2. CreateXmlDeclaration用于创建XML声明,指定版本、编码和独立性。

      1
      2
      3
      //2.创建一个声明<?xml version="1.0" encoding="utf-8" ?>
      XmlDeclaration xmlDecl = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
      xmlDoc.AppendChild(xmlDecl);//将声明添加到文档的子节点中
    3. CreateElement用于创建XML元素,可以设置其名称。

      1
      2
      //3.创建节点
      XmlElement xmlEle = xmlDoc.CreateElement("Person");
    4. SetAttribute用于给元素添加属性。

      1
      2
      3
      4
      //4.创建根节点的子元素
      XmlElement xmlEleNode = xmlDoc.CreateElement("student");
      //给子元素添加属性 <student studentNo="1001">
      xmlEleNode.SetAttribute("studentNo", "1001");
    5. InnerText用于设置元素的文本内容。

      1
      2
      3
      //创建子元素 <name>张三</name> 
      XmlElement xmlNode1 = xmlDoc.CreateElement("name");
      xmlNode1.InnerText = "张三";
    6. AppendChild用于将元素添加到父元素下。

      1
      xmlEleNode.AppendChild(xmlNode1);
    7. 最后使用Save方法将XML文档保存到指定文件。

      1
      2
      //5.保存XML文件
      xmlDoc.Save("student.xml");
  2. 实例,通过C#代码,实现保存XML的学生文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    using System.Xml;

    namespace XML_Project
    {
    internal class Program
    {
    static void Main(string[] args)
    {
    //1.创建一个新的XML文档对象
    XmlDocument xmlDoc = new XmlDocument();

    //2.创建一个声明<?xml version="1.0" encoding="utf-8" ?>
    XmlDeclaration xmlDecl = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
    xmlDoc.AppendChild(xmlDecl);//将声明添加到文档的子节点中

    //3.创建根节点
    XmlElement xmlEle = xmlDoc.CreateElement("Person");
    xmlDoc.AppendChild(xmlEle);//添加根节点

    //4.创建根节点的子元素
    XmlElement xmlEleNode = xmlDoc.CreateElement("student");
    //给子元素添加属性
    xmlEleNode.SetAttribute("studentNo", "1001");
    //给子元素添加子元素
    XmlElement xmlNode1 = xmlDoc.CreateElement("name");
    xmlNode1.InnerText = "张三";
    XmlElement xmlNode2 = xmlDoc.CreateElement("age");
    xmlNode2.InnerText = "20";
    XmlElement xmlNode3 = xmlDoc.CreateElement("gender");
    xmlNode3.InnerText = "男";

    xmlEleNode.AppendChild(xmlNode1);
    xmlEleNode.AppendChild(xmlNode2);
    xmlEleNode.AppendChild(xmlNode3);
    xmlEle.AppendChild(xmlEleNode);

    //5.保存
    xmlDoc.Save("student.xml");

    Console.ReadLine();
    }
    }
    }

    保存后文件:

    1722059180039

4、C#操作XML文件

  1. 读取XML文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    //创建XMLDocument对象
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.Load("student.xml");//加载XML文件

    //获取根元素
    XmlElement rootElement = xmlDoc.DocumentElement;

    //遍历根节点的子元素
    foreach (XmlElement xmlEle in rootElement.ChildNodes)
    {
    Console.WriteLine($"元素名称:{xmlEle.Name}");
    Console.WriteLine($"学生学号:{xmlEle.GetAttribute("studentNo")}");

    Console.WriteLine($"姓名:{xmlEle["name"].InnerText}");
    Console.WriteLine($"年龄:{xmlEle["age"].InnerText}");
    Console.WriteLine($"性别:{xmlEle["gender"].InnerText}");
    /*foreach (XmlElement xmlChildEle in xmlEle.ChildNodes)
    {
    if (xmlChildEle.Name == "name")
    {
    Console.WriteLine($"姓名:{xmlChildEle.InnerText}");
    }
    else if (xmlChildEle.Name == "age")
    {
    Console.WriteLine($"年龄:{xmlChildEle.InnerText}");
    }
    else
    {
    Console.WriteLine($"性别:{xmlChildEle.InnerText}");
    }

    }*/
    }
  2. 更新XML文件内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.Load("student.xml");//加载XML文件

    //找到要更新的元素
    XmlNode xmlNode = xmlDoc.SelectSingleNode("//student");

    xmlNode.Attributes["studentNo"].Value = "1002";//修改属性
    xmlNode.InnerText = "张三";

    xmlDoc.Save("student.xml");

    注释:

    使用SelectSingleNode方法通过XPath表达式定位要更新的元素。

    直接修改找到的元素的属性值和文本内容。

    保存更改到文件。

  3. 移除指定节点

    1
    2
    3
    4
    5
    6
    7
    8
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.Load("student.xml");//加载XML文件

    //找到要更新的元素
    XmlNode xmlNode = xmlDoc.SelectSingleNode("//student");
    xmlNode.ParentNode.RemoveChild(xmlNode);//从指定节点的父节点中移除

    xmlDoc.Save("student.xml");

    注释:

    使用SelectSingleNode方法通过XPath表达式定位要删除的元素。

    调用RemoveChild方法从其父节点移除该元素。

    保存更改到文件。

  4. XPath筛选节点数据

    在C#中,可以使用XPath来筛选XML节点数据。XPath是一种用于在XML文档中查找信息的语言,它可以用来在XML文档中对元素和属性进行遍历。

    XPath常见节点选择方法:

    //:选择所有的节点,包括根节点。

    .:选择当前节点。

    ..:选择当前节点的父节点。

    /:选择根节点下的所有节点。

    //A:选择所有名为”A”的节点。

    //A/B:选择所有名为”A”的节点的”B”子节点。

    //A/*:选择所有名为”A”的节点下的所有任意节点

    //A[1]:选择文档中第一个名为”A”的节点。

    //A[@属性=’属性值’]:选择所有名为”A”的节点,且属性=属性值的节点。

    //A[contains(@属性, “属性值”)]:选择所有名为”A”的节点,且属性包含属性值的节点。

    //A[B=’C’]:选择所有名为”A”的且子节点B等于’C’的节点。

    //A[B!=’C’]:选择所有名为”A”的且子节点B不等于’C’的节点。

    //A[B!=’C’]:选择所有名为”A”的且子节点B不等于’C’的节点。

    //A[B>’C’]:选择所有名为”A”的且子节点B大于’C’的节点。

    //A[B<’C’]:选择所有名为”A”的且子节点B小于’C’的节点。

    //A[B>=’C’]:选择所有名为”A”的且子节点B大于等于’C’的节点。

    //A[B<=’C’]:选择所有名为”A”的且子节点B小于等于’C’的节点。

    //A[B<=’C’ and B>=’D’]:选择所有名为”A”的且子节点B小于等于’C’且B大于等于’D’的节点。

    //A[B<=’C’ or B>=’D’]:选择所有名为”A”的且子节点B小于等于’C’或者B大于等于’D’的节点。

    //*[@属性=’属性值’]:选择所有属性=属性值的节点。

    //A[@属性=’属性值’][1]:选择文档中第一个名为”A”的节点,且属性=属性值的节点。

    //A[@属性=’属性值’]/B:选择所有名为”A”的节点,且属性=属性值的节点的”B”子节点。

5、综合案例

  1. 解析FullChannels.xml文件获取频道信息,效果如下:

    1722065253690

    FullChannels.xml文件,参照提供素材:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?xml version="1.0" encoding="utf-8" ?>
    <TVChannels>
    <Channel>
    <channelType>TypeA</channelType> <!--频道类型-->
    <tvChannel>北京电视台</tvChannel> <!--频道名称-->
    <path>files/北京电视台.xml</path> <!--频道对应XML文件的本地路径-->
    </Channel>
    <Channel>
    <channelType>TypeB</channelType>
    <tvChannel>凤凰卫视</tvChannel>
    <path>files/凤凰卫视.xml</path>
    </Channel>
    </TVChannels>

    参考代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.Load("FullChannels.xml");

    //获取根元素
    XmlElement xmlElement = xmlDoc.DocumentElement;

    //遍历根元素下的子节点
    foreach (XmlNode xmlNode in xmlElement.ChildNodes)
    {
    Console.WriteLine($"{xmlNode["channelType"].InnerText}\t{xmlNode["tvChannel"].InnerText}\t{xmlNode["path"].InnerText}");
    }

本章总结

1722066279821

本章作业

  1. 创建XML文件,具体需求说明如下:

    1. XML可保存多个学生
    2. 学生中有姓名,年龄,性别
  2. 通过C#对XML文件操作,实现创建题目1的xml文件,分别实现修改,移除,添加节点等功能。

  3. 创建以下XML文件,且通过C#实现效果图

    1. XML文件如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      <?xml version="1.0" encoding="utf-8" ?>
      <Engineer>
      <ID>1002</ID>
      <Name>张靓</Name>
      <Age>20</Age>
      <ID>1001</ID>
      <Name>周杰</Name>
      <Age>22</Age>
      </Engineer>
    2. 实现效果图:

      1722066529981

  4. 获取所有电视频道:

    1. 需求说明:

      解析FullChannels.xml文件,输出频道类型、频道名称和频道节目单本地路径

    2. 效果图:

      1722066611002

  5. 解析频道节目单(XML素材见提供学生素材中)

    1. 需求说明:

      1. 分别解析TypeA类型及 TypeB类型的频道节目单
        1. 北京电视台节目单格式 为TypeA类型
        2. 凤凰卫视电视台节目单 格式为TypeB类型
    2. 实现思路

      1. 分析XML节点之间的关系
      2. 创建类ChannelManager,编写方法封装电视频道信息解析
      3. 编写抽象类ChannelBase存储频道基本信息,定义抽象方法Fetch()解析频道节目单信息
      4. 编写TypeAChannel以及TypeBChannel类继承ChannelBase类,重写其Fetch()方法,分别完成TypeA类型以及TypeB类型的频道节目单信息解析
    3. 效果图:

      1722066807212

      1722066822968

  6. 显示所有频道

    1. 需求说明:

      显示网络电视精灵树状菜单中“我的电视台”及“所有电视台”下的所有频道列表

    2. 效果图如下:

      1722066943427

  7. 定制频道

    1. 需求说明:
      1. 定制我的频道:右键选择频道,单击“添加”,添加到“我的电视台”
      2. “所有电视台”节点只允许“添加”操作
      3. “我的电视台”节点只允许“删除”操作
    2. 实现思路:
      1. 右键菜单“添加”事件
        1. 获取选中节点,根据Tag属性获对应频道对象
        2. 遍历“我的电视台”,查看是否已定制
        3. 将定制的频道对象添加到myFavor集合
        4. 刷新TreeView显示
      2. 修改UpdateTreeView()方法,添加遍历“我的电视台”集合对象并加载信息
      3. 编写TreeView控件MouseClick事件,控制右键菜单显示
  8. 显示节目单

    1. 需求说明

      单击电视台频道节点,DataGridView显示频道对应节目单

      1722067151227