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);
}
总结
读取XML文件
- XmlDocument xmlDocument = new XmlDocument();
- 读取文本方式1-xmlDocument.LoadXml(传入xml文本字符串)
- 读取文本方式2-xmlDocument.Load(传入路径)
读取元素和属性
获取单个节点 : 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