5.读取Xml文件

  1. 5.CSharp操作XML-读取XML文件
    1. 5.1 知识点
      1. C#读取XML的方式
      2. 读取xml文件信息
        1. XmlDocument Xml文档类
        2. XmlDocument读取xml文件
          1. XmlDocument.LoadXml方法 传入xml字符串内容来加载xml文件
          2. XmlDocument.Load方法 通过xml文件的路径加载
          3. 加载完成后 XML文档的所有信息就存在XML文档对象中
      3. 读取元素和属性信息
        1. XmlNode Xml节点信息类
        2. XmlNodeList Xml节点列表信息类
        3. XmlDocument.SelectSingleNode方法 获取xml当中的根节点
        4. XmlNode.SelectSingleNode方法 通过根节点去获取下面的子节点
        5. XmlNode.InnerText变量 获取节点包裹的元素信息
        6. 获得Xml节点中的属性信息
          1. XmlNode.Attributes[“属性名”].Value 直接中括号获取信息
          2. XmlNode.Attributes.GetNamedItem(“属性名”).Value 用GetNamedItem方法获取信息
        7. XmlNode.SelectNodes方法 获取一个节点下的同名节点的方法
        8. 遍历获得XmlNodeList每个节点信息
          1. 迭代器遍历
          2. for循环遍历
      4. 总结
    2. 5.2 知识点代码
      1. TestXml.xml
      2. LoadXml
    3. 5.3 练习题
      1. 有一个玩家数据类,请为该类写一个方法结合XML读取知识点,将XML中数据读取到PlayerInfo的一个对象中
        1. StreamingAssets文件夹下创建PlayerInfo.xml
      2. PlayerInfo.xml
        1. 定义Item类
        2. 定义一个名为 PlayerInfo 的公共类
        3. PlayerInfo中定义一个名为 LoadData 的公共方法,参数为文件名字符串 fileName
        4. 创建测试脚本,测试脚本中断点测试看能不能获得XML文件数据
    4. 5.4 练习题代码
      1. PlayerInfo
      2. Test
      3. PlayerInfo.xml

5.CSharp操作XML-读取XML文件


5.1 知识点

C#读取XML的方式

  • XmlDocument(把数据加载到内存中,方便读取)

  • XmlTextReader(以流形式加载,内存占用更少,但是是单向只读,使用不是特别方便,除非有特殊需求,否则不会使用)

  • Linq(以后专门讲Linq的时候讲)

  • 使用XmlDocument类读取是较方便最容易理解和操作的方法

  • 现在在Resources文件夹和StreamingAssets文件夹分别放入以下TestXml.xml

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <name>林文韬</name>
    <age>18</age>
    <Item id="1" num="10"/>
    <Friend>
        <name>小明</name>
        <age>8</age>
    </Friend>
    <Friend>
        <name>小红</name>
        <age>10</age>
    </Friend>
</Root>

读取xml文件信息

XmlDocument Xml文档类

  • 引用 System.Xml 命名空间
  • 表示XML文档的类 XmlDocument
  • 新建一个XML文档对象
XmlDocument xmlDocument = new XmlDocument();

XmlDocument读取xml文件

XmlDocument.LoadXml方法 传入xml字符串内容来加载xml文件
//加载存放在Resources文件夹下的xml文件 类型是TextAsset
TextAsset textAsset = Resources.Load<TextAsset>("TestXml");
print(textAsset.text);//可以输出xml文本
//XmlDocument类中的LoadXml方法 能够翻译字符串为xml对象
xmlDocument.LoadXml(textAsset.text);
XmlDocument.Load方法 通过xml文件的路径加载
//XML文件要在StreamingAssets文件夹下 因为StreamingAssets不会被压缩加密 Resources文件夹会
//XmlDocument类中的Load方法 传入xml文件的路径直接加载xml
xmlDocument.Load(Application.streamingAssetsPath + "/TestXml.xml");
加载完成后 XML文档的所有信息就存在XML文档对象中

读取元素和属性信息

XmlNode Xml节点信息类

XmlNodeList Xml节点列表信息类

XmlDocument.SelectSingleNode方法 获取xml当中的根节点

//XmlDocument中的SelectSingleNode方法 获取xml当中的根节点
XmlNode root = xmlDocument.SelectSingleNode("Root");

XmlNode.SelectSingleNode方法 通过根节点去获取下面的子节点

//XmlNode中的SelectSingleNode方法 再通过根节点 去获取下面的子节点
XmlNode nodeName = root.SelectSingleNode("name");

XmlNode.InnerText变量 获取节点包裹的元素信息

//XmlNode中的InnerText变量 获取节点包裹的元素信息
//如果想要获取节点包裹的元素信息 直接 .InnerText
print(nodeName.InnerText);//林文韬
XmlNode nodeAge = root.SelectSingleNode("age");
print(nodeAge.InnerText);//18

获得Xml节点中的属性信息

XmlNode nodeItem = root.SelectSingleNode("Item");
XmlNode.Attributes[“属性名”].Value 直接中括号获取信息
//XmlNode中的Attributes用中括号传入对应属性名字后.出Value  直接中括号获取信息
print(nodeItem.Attributes["id"].Value);//1
print(nodeItem.Attributes["num"].Value);//10
XmlNode.Attributes.GetNamedItem(“属性名”).Value 用GetNamedItem方法获取信息
//XmlNode中的Attributes用GetNamedItem方法传入对应属性名字后.出Value  用GetNamedItem方法获取信息
print(nodeItem.Attributes.GetNamedItem("id").Value);//1
print(nodeItem.Attributes.GetNamedItem("num").Value);//10

XmlNode.SelectNodes方法 获取一个节点下的同名节点的方法

//XmlNode中的SelectNodes方法 获取一个节点下的同名节点的方法
XmlNodeList friendList = root.SelectNodes("Friend");

遍历获得XmlNodeList每个节点信息

迭代器遍历
//遍历方式一:迭代器遍历
foreach (XmlNode item in friendList)
{
    //相当于item选择是父节点了 像单个节点一样获得子节点
    print(item.SelectSingleNode("name").InnerText);
    print(item.SelectSingleNode("age").InnerText);
}
for循环遍历
//遍历方式二:通过for循环遍历
//通过XmlNodeList中的 成员变量 Count可以得到 节点数量
for (int i = 0; i < friendList.Count; i++)
{
    print(friendList[i].SelectSingleNode("name").InnerText);
    print(friendList[i].SelectSingleNode("age").InnerText);
}

总结

  1. 读取XML文件

    • XmlDocument xmlDocument = new XmlDocument();
    • 读取文本方式1-xmlDocument.LoadXml(传入xml文本字符串)
    • 读取文本方式2-xmlDocument.Load(传入路径)
  2. 读取元素和属性

    • 获取单个节点 : XmlNode node = xmlDocument.SelectSingleNode(节点名)

    • 获取多个节点 : XmlNodeList nodeList = xmlDocument.SelectNodes(节点名)

    • 获取节点元素内容:node.InnerText

    • 获取节点元素属性:

      • item.Attributes[“属性名”].Value
      • item.Attributes.GetNamedItem(“属性名”).Value
    • 通过迭代器遍历或者循环遍历XmlNodeList对象可以获取到各单个元素节点


5.2 知识点代码

TestXml.xml

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <name>林文韬</name>
    <age>18</age>
    <Item id="1" num="10"/>
    <Friend>
        <name>小明</name>
        <age>8</age>
    </Friend>
    <Friend>
        <name>小红</name>
        <age>10</age>
    </Friend>
</Root>

LoadXml

using System.Collections;
using System.Collections.Generic;
using System.Xml;
using UnityEngine;

public class LoadXml : MonoBehaviour
{
    void Start()
    {
        #region 知识点一 C#读取XML的方式 

        //1.XmlDocument    (把数据加载到内存中,方便读取)
        //2.XmlTextReader  (以流形式加载,内存占用更少,但是是单向只读,使用不是特别方便,除非有特殊需求,否则不会使用)
        //3.Linq           (以后专门讲Linq的时候讲)

        //使用XmlDocument类读取是较方便最容易理解和操作的方法

        #endregion

        #region 知识点二 读取xml文件信息

        //引用 System.Xml 命名空间
        //表示XML文档的类 XmlDocument 
        //新建一个XML文档对象
        XmlDocument xmlDocument = new XmlDocument();

        //通过XmlDocument读取xml文件 有两种方法

        //1.直接根据xml字符串内容 来加载xml文件
        //加载存放在Resources文件夹下的xml文件 类型是TextAsset
        TextAsset textAsset = Resources.Load<TextAsset>("TestXml");
        print(textAsset.text);//可以输出xml文本
        //XmlDocument类中的LoadXml方法 能够翻译字符串为xml对象
        xmlDocument.LoadXml(textAsset.text);

        //2.通过xml文件的路径去进行加载
        //XML文件要在StreamingAssets文件夹下 因为StreamingAssets不会被压缩加密 Resources文件夹会
        //XmlDocument类中的Load方法 传入xml文件的路径直接加载xml
        xmlDocument.Load(Application.streamingAssetsPath + "/TestXml.xml");

        //加载完成后 XML文档的所有信息就存在XML文档对象中

        #endregion

        #region 知识点三 读取元素和属性信息

        //节点信息类 XmlNode
        //XmlNode 单个节点信息类

        //节点列表信息类 XmlNodeList
        //XmlNodeList 多个节点信息类

        //XmlDocument中的SelectSingleNode方法 获取xml当中的根节点
        XmlNode root = xmlDocument.SelectSingleNode("Root");

        //XmlNode中的SelectSingleNode方法 再通过根节点 去获取下面的子节点
        XmlNode nodeName = root.SelectSingleNode("name");

        //XmlNode中的InnerText变量 获取节点包裹的元素信息
        //如果想要获取节点包裹的元素信息 直接 .InnerText
        print(nodeName.InnerText);//林文韬
        XmlNode nodeAge = root.SelectSingleNode("age");
        print(nodeAge.InnerText);//18

        //获得Xml节点中的属性信息
        //有两种方式
        XmlNode nodeItem = root.SelectSingleNode("Item");
        //XmlNode中的Attributes用中括号传入对应属性名字后.出Value  直接中括号获取信息
        print(nodeItem.Attributes["id"].Value);//1
        print(nodeItem.Attributes["num"].Value);//10
        //XmlNode中的Attributes用GetNamedItem方法传入对应属性名字后.出Value  用GetNamedItem方法获取信息
        print(nodeItem.Attributes.GetNamedItem("id").Value);//1
        print(nodeItem.Attributes.GetNamedItem("num").Value);//10

        //XmlNode中的SelectNodes方法 获取一个节点下的同名节点的方法
        XmlNodeList friendList = root.SelectNodes("Friend");

        //遍历获得XmlNodeList节点信息的方式

        //遍历方式一:迭代器遍历
        foreach (XmlNode item in friendList)
        {
            //相当于item选择是父节点了 像单个节点一样获得子节点
            print(item.SelectSingleNode("name").InnerText);
            print(item.SelectSingleNode("age").InnerText);
        }

        //遍历方式二:通过for循环遍历
        //通过XmlNodeList中的 成员变量 Count可以得到 节点数量
        for (int i = 0; i < friendList.Count; i++)
        {
            print(friendList[i].SelectSingleNode("name").InnerText);
            print(friendList[i].SelectSingleNode("age").InnerText);
        }
        #endregion

        #region 总结

        //1.读取XML文件
        //XmlDocument xmlDocument = new XmlDocument();
        //读取文本方式1-xmlDocument.LoadXml(传入xml文本字符串)
        //读取文本方式2-xmlDocument.Load(传入路径)

        //2.读取元素和属性
        //获取单个节点 : XmlNode node = xmlDocument.SelectSingleNode(节点名)
        //获取多个节点 : XmlNodeList nodeList = xmlDocument.SelectNodes(节点名)

        //获取节点元素内容:node.InnerText
        //获取节点元素属性:
        //1.item.Attributes["属性名"].Value
        //2.item.Attributes.GetNamedItem("属性名").Value

        //通过迭代器遍历或者循环遍历XmlNodeList对象 可以获取到各单个元素节点

        #endregion
    }

}

5.3 练习题

有一个玩家数据类,请为该类写一个方法结合XML读取知识点,将XML中数据读取到PlayerInfo的一个对象中

StreamingAssets文件夹下创建PlayerInfo.xml

PlayerInfo.xml

<?xml version="1.0" encoding="UTF-8"?>
<PlayerInfo>
    <!--自己定一个xml代表 类对象数据的规则
    我们的元素节点名 就用我们的变量名命名
    -->
    <name>韬老狮</name>
    <atk>10</atk>
    <def>5</def>
    <moveSpeed>20</moveSpeed>
    <roundSpeed>20</roundSpeed>
    <weapon>
        <id>1</id>
        <num>1</num>
    </weapon>
    <!--当出现没有变量名的数据时 我们就用变量类型名命名-->
    <listInt>
        <int>1</int>
        <int>2</int>
        <int>3</int>
    </listInt>
    <itemList>
        <Item id="1" num="10"/>
        <Item id="2" num="20"/>
        <Item id="3" num="30"/>
        <Item id="4" num="40"/>
    </itemList>
    <itemDic>
        <int>1</int>
        <Item id="1" num="1"/>
        <int>2</int>
        <Item id="2" num="1"/>
        <int>3</int>
        <Item id="3" num="1"/>
        <!-- 另一种写法 但是建议大家都统一
        <int>4</int>
        <Item>
            <id>4</id>
            <num>1</num>
        </Item>
        -->
    </itemDic>
</PlayerInfo>

定义Item类

// 定义Item类
public class Item
{
    public int id;
    public int num;
}

定义一个名为 PlayerInfo 的公共类

//定义一个名为 PlayerInfo 的公共类
public class PlayerInfo
{
    //以下为 PlayerInfo 类的成员变量
    //玩家昵称,字符串类型
    public string name;
    //攻击力,整型
    public int atk;
    //防御力,整型
    public int def;
    //移动速度,浮点型
    public float moveSpeed;
    //旋转速度,浮点型
    public float roundSpeed;
    //武器信息,Item 类型
    public Item weapon;
    //整数列表,使用 List<int> 实现
    public List<int> listInt;
    //物品列表,使用 List<Item> 实现
    public List<Item> itemList;
    //物品字典,使用 Dictionary<int, Item> 实现
    public Dictionary<int, Item> itemDic;
}

PlayerInfo中定义一个名为 LoadData 的公共方法,参数为文件名字符串 fileName

//定义一个名为 LoadData 的公共方法,参数为文件名字符串 fileName
public void LoadData(string fileName)
{
    //构建文件路径,用于读取玩家存档数据
    string path = Application.persistentDataPath + "/" + fileName + ".xml";

    //如果存档文件不存在,则从默认资源中获取数据
    if (!File.Exists(path))
    {
        path = Application.streamingAssetsPath + "/" + fileName + ".xml";
    }

    //加载 XML 文件信息
    XmlDocument xml = new XmlDocument();
    //加载
    xml.Load(path);

    //从文件中加载出具体的数据

    //加载根节点才能加载后面的内容
    XmlNode playerInfo = xml.SelectSingleNode("PlayerInfo");

    //通过根节点去加载具体的信息
    this.name = playerInfo.SelectSingleNode("name").InnerText;
    this.atk = int.Parse(playerInfo.SelectSingleNode("atk").InnerText);
    this.def = int.Parse(playerInfo.SelectSingleNode("def").InnerText);
    this.moveSpeed = float.Parse(playerInfo.SelectSingleNode("moveSpeed").InnerText);
    this.roundSpeed = float.Parse(playerInfo.SelectSingleNode("roundSpeed").InnerText);

    //加载武器信息节点
    XmlNode weaponNode = playerInfo.SelectSingleNode("weapon");
    this.weapon = new Item();
    this.weapon.id = int.Parse(weaponNode.SelectSingleNode("id").InnerText);
    this.weapon.num = int.Parse(weaponNode.SelectSingleNode("num").InnerText);

    //加载整数列表节点
    XmlNode listIntNode = playerInfo.SelectSingleNode("listInt");
    XmlNodeList intList = listIntNode.SelectNodes("int");
    this.listInt = new List<int>();
    for (int i = 0; i < intList.Count; i++)
    {
        this.listInt.Add(int.Parse(intList[i].InnerText));
    }

    //加载物品列表节点
    XmlNode itemListNode = playerInfo.SelectSingleNode("itemList");
    XmlNodeList items = itemListNode.SelectNodes("Item");
    this.itemList = new List<Item>();
    foreach (XmlNode item in items)
    {
        Item item2 = new Item();
        item2.id = int.Parse(item.Attributes["id"].Value);
        item2.num = int.Parse(item.Attributes["num"].Value);
        this.itemList.Add(item2);
    }

    //加载物品字典节点
    XmlNode itemDicNode = playerInfo.SelectSingleNode("itemDic");
    XmlNodeList keyInt = itemDicNode.SelectNodes("int");
    XmlNodeList valueItem = itemDicNode.SelectNodes("Item");

    this.itemDic = new Dictionary<int, Item>();
    for (int i = 0; i < keyInt.Count; i++)
    {
        int key = int.Parse(keyInt[i].InnerText);
        Item value = new Item();
        value.id = int.Parse(valueItem[i].Attributes["id"].Value);
        value.num = int.Parse(valueItem[i].Attributes["num"].Value);
        this.itemDic.Add(key, value);
    }
}

创建测试脚本,测试脚本中断点测试看能不能获得XML文件数据

PlayerInfo p = new PlayerInfo();
p.LoadData("PlayerInfo");

5.4 练习题代码

PlayerInfo

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEngine;

// 定义Item类
public class Item
{
    public int id;
    public int num;
}

//定义一个名为 PlayerInfo 的公共类
public class PlayerInfo
{
    //以下为 PlayerInfo 类的成员变量
    //玩家昵称,字符串类型
    public string name;
    //攻击力,整型
    public int atk;
    //防御力,整型
    public int def;
    //移动速度,浮点型
    public float moveSpeed;
    //旋转速度,浮点型
    public float roundSpeed;
    //武器信息,Item 类型
    public Item weapon;
    //整数列表,使用 List<int> 实现
    public List<int> listInt;
    //物品列表,使用 List<Item> 实现
    public List<Item> itemList;
    //物品字典,使用 Dictionary<int, Item> 实现
    public Dictionary<int, Item> itemDic;

    //定义一个名为 LoadData 的公共方法,参数为文件名字符串 fileName
    public void LoadData(string fileName)
    {
        //构建文件路径,用于读取玩家存档数据
        string path = Application.persistentDataPath + "/" + fileName + ".xml";

        //如果存档文件不存在,则从默认资源中获取数据
        if (!File.Exists(path))
        {
            path = Application.streamingAssetsPath + "/" + fileName + ".xml";
        }

        //加载 XML 文件信息
        XmlDocument xml = new XmlDocument();
        //加载
        xml.Load(path);

        //从文件中加载出具体的数据

        //加载根节点才能加载后面的内容
        XmlNode playerInfo = xml.SelectSingleNode("PlayerInfo");

        //通过根节点去加载具体的信息
        this.name = playerInfo.SelectSingleNode("name").InnerText;
        this.atk = int.Parse(playerInfo.SelectSingleNode("atk").InnerText);
        this.def = int.Parse(playerInfo.SelectSingleNode("def").InnerText);
        this.moveSpeed = float.Parse(playerInfo.SelectSingleNode("moveSpeed").InnerText);
        this.roundSpeed = float.Parse(playerInfo.SelectSingleNode("roundSpeed").InnerText);

        //加载武器信息节点
        XmlNode weaponNode = playerInfo.SelectSingleNode("weapon");
        this.weapon = new Item();
        this.weapon.id = int.Parse(weaponNode.SelectSingleNode("id").InnerText);
        this.weapon.num = int.Parse(weaponNode.SelectSingleNode("num").InnerText);

        //加载整数列表节点
        XmlNode listIntNode = playerInfo.SelectSingleNode("listInt");
        XmlNodeList intList = listIntNode.SelectNodes("int");
        this.listInt = new List<int>();
        for (int i = 0; i < intList.Count; i++)
        {
            this.listInt.Add(int.Parse(intList[i].InnerText));
        }

        //加载物品列表节点
        XmlNode itemListNode = playerInfo.SelectSingleNode("itemList");
        XmlNodeList items = itemListNode.SelectNodes("Item");
        this.itemList = new List<Item>();
        foreach (XmlNode item in items)
        {
            Item item2 = new Item();
            item2.id = int.Parse(item.Attributes["id"].Value);
            item2.num = int.Parse(item.Attributes["num"].Value);
            this.itemList.Add(item2);
        }

        //加载物品字典节点
        XmlNode itemDicNode = playerInfo.SelectSingleNode("itemDic");
        XmlNodeList keyInt = itemDicNode.SelectNodes("int");
        XmlNodeList valueItem = itemDicNode.SelectNodes("Item");

        this.itemDic = new Dictionary<int, Item>();
        for (int i = 0; i < keyInt.Count; i++)
        {
            int key = int.Parse(keyInt[i].InnerText);
            Item value = new Item();
            value.id = int.Parse(valueItem[i].Attributes["id"].Value);
            value.num = int.Parse(valueItem[i].Attributes["num"].Value);
            this.itemDic.Add(key, value);
        }
    }
}

Test

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    void Start()
    {
        PlayerInfo p = new PlayerInfo();
        p.LoadData("PlayerInfo");
    }
}

PlayerInfo.xml

<?xml version="1.0" encoding="UTF-8"?>
<PlayerInfo>
    <!--自己定一个xml代表 类对象数据的规则
    我们的元素节点名 就用我们的变量名命名
    -->
    <name>韬老狮</name>
    <atk>10</atk>
    <def>5</def>
    <moveSpeed>20</moveSpeed>
    <roundSpeed>20</roundSpeed>
    <weapon>
        <id>1</id>
        <num>1</num>
    </weapon>
    <!--当出现没有变量名的数据时 我们就用变量类型名命名-->
    <listInt>
        <int>1</int>
        <int>2</int>
        <int>3</int>
    </listInt>
    <itemList>
        <Item id="1" num="10"/>
        <Item id="2" num="20"/>
        <Item id="3" num="30"/>
        <Item id="4" num="40"/>
    </itemList>
    <itemDic>
        <int>1</int>
        <Item id="1" num="1"/>
        <int>2</int>
        <Item id="2" num="1"/>
        <int>3</int>
        <Item id="3" num="1"/>
        <!-- 另一种写法 但是建议大家都统一
        <int>4</int>
        <Item>
            <id>4</id>
            <num>1</num>
        </Item>
        -->
    </itemDic>
</PlayerInfo>


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏