Unity:XML笔记(一)——Xml文件格式、读取Xml文件、存储修改Xml文件

发布于:2025-09-02 ⋅ 阅读:(18) ⋅ 点赞:(0)

写在前面:

写本系列(自用)的目的是回顾已经学过的知识、记录新学习的知识或是记录心得理解,方便自己以后快速复习,减少遗忘。

一、XML文件格式

1、基本语法

(1)注释

xml注释的格式是:<!--注释内容-->,如下:

<!--在其中书写注释相关内容-->
<!--
多行注释
-->

(2)必须语句

XML中,第一行必须写:<?xml version="1.0" encoding="UTF-8"?>,否则打开xml会报错。其中,version代表版本 encoding代表编码格式。

编码格式:不同的字符在内存中的二进制是不一样的,每一个字符对应一个数字,不同的编码格式字符对应的二进制是不一样的。乱码出现的情况就是因为用了不一样的编码格式去解析文本内容。

<?xml version="1.0" encoding="UTF-8"?>

(3)基本格式

XML文档每个节点的固定格式是:<节点名>数据或者包裹别的节点</节点名>。并且,XML文档必须有根元素。从这个格式可以看出,每个元素都必须有关闭标签即</节点名>。元素命名规则基本遵照C#中变量命名规则。

XML标签对大小写敏感,例如<name>和<Name>是不同的。下面是实例:

<PlayerInfo>
	<name>张三</name>
	<atk>10</atk>
	<ItemList>
		<Item>
			<id>1</id>
			<num>10</num>
		</Item>
		<Item>
			<id>2</id>
			<num>10</num>
		</Item>
		<Item>
			<id>3</id>
			<num>20</num>
		</Item>
	</ItemList>
</PlayerInfo>

特殊的符号应该用实体引用

< 小于 : &lt

> 大于 :&gt

&和 : &amp

' 单引号 :&apos

" 引号 :&quot

2、XML属性

(1)属性的语法

属性的写法是  属性 通过空格隔开 属性名 = 引号包裹的内容

以上节为例:如果不希望在Item之间包裹节点就可以将节点写为属性:

<Item id = '3' num = '20'></Item>,中间没有节点还可以继续简写:<Item id = '2' num = '10'/>

需要注意的是,属性一定要是引号包裹的。

<PlayerInfo>
	<name>张三</name>
	<atk>10</atk>
	<ItemList>
		<Item id = '1' num = '10'/>
		<Item id = '2' num = '10'/>
		<Item id = '3' num = '20'></Item>
	</ItemList>
</PlayerInfo>

(2)属性和元素节点的区别

只是写法上的区别,可以自行选择

(3)如何查语法错误

元素标签必须配对、属性必须有引号、注意命名

二、读取Xml文件

1、Xml文件存放位置

只读不写的XML文件,可以放在Resources或者StreamingAssets文件夹下;

动态存储的XML文件,放在Application.persistentDataPath路径下

2、读取Xml文件

(1)读取xml文件信息

xml文档的类型是:XmlDocument。先创建一个xml类型的变量:XmlDocument xml = new XmlDocument()。

有两种读取Xml文件信息的方法:

第一种:xml文件位于Resources文件夹中。

我们需要先将该文件以字符串的形式导入:

TextAsset asset = Resources.Load<TextAsset>("TestXml");

然后加载进创建的xml变量中:xml.LoadXml(asset.text);

通过这个方法就可以将字符串翻译为xml对象。

第二种:xml文件位于StreamingAssets文件夹中。

我们可以直接通过路径加载:xml.Load(Application.streamingAssetsPath + "/TestXml.xml");

void Start()
{
    XmlDocument xml = new XmlDocument();

    //第一种
    TextAsset asset = Resources.Load<TextAsset>("TestXml");
    print(asset.text);

    xml.LoadXml(asset.text);

    //第二种
    xml.Load(Application.streamingAssetsPath + "/TestXml.xml");
}

(2)读取元素和属性信息

①得到单个节点

Xml有两种节点信息类:XmlNode—单个节点信息类;XmlNodeList—多个节点信息类。

得到xml后,就可以获得xml的根节点,而后通过根节点读取到一系列的节点元素。获取单个节点的方法是:.SelectSingleNode(),括号中传入节点名。

以获取如下xml文档的元素和属性信息为例:

<?xml version = "1.0" encoding = "UTF-8"?>

<Root>
	<name>Alice</name>
	<age>18</age>
	<Item id = "1" num = "10"/>
	<Friend>
		<name>Max</name>
		<age>20</age>
    </Friend>
    <Friend>
		<name>Caroline</name>
		<age>19</age>
	</Friend>
</Root>

首先获取根节点:XmlNode root = xml.SelectSingleNode("Root");

获取根节点后,就可以通过根节点获得其子节点:

XmlNode nodeName = root.SelectSingleNode("name");

并通过nodeName.InnerText来获取子节点的信息,从以上xml文件可以看出,该子节点的信息是Alice。

void Start()
{
    XmlDocument xml = new XmlDocument();

    xml.Load(Application.streamingAssetsPath + "/TestXml.xml");

    XmlNode root = xml.SelectSingleNode("Root");

    XmlNode nodeName = root.SelectSingleNode("name");
    print(nodeName.InnerText);

    XmlNode nodeAge = root.SelectSingleNode("age");
    print(nodeAge.InnerText);
}

②得到属性

为了得到<Item id = "1" num = "10"/>节点的属性,我们可以先得到Item节点,然后通过节点去获取属性。有两种获取方式:

第一种:nodeItem.Attributes["id"].Value

第二种:nodeItem.Attributes.GetNamedItem("id").Value

void Start()
{
    XmlDocument xml = new XmlDocument();

    XmlNode nodeItem = root.SelectSingleNode("Item");
    //第一种方式
    print(nodeItem.Attributes["id"].Value);
    print(nodeItem.Attributes["num"].Value);
    //第二种方式
    print(nodeItem.Attributes.GetNamedItem("id").Value);
    print(nodeItem.Attributes.GetNamedItem("num").Value);
}

③得到同名节点

在测试的xml文件中

<Friend>
        <name>Max</name>
        <age>20</age>
        <name>Caroline</name>
        <age>19</age>
</Friend>

Friend节点下的子节点显然有重名的,为了得到所有的重名节点,可以通过多个节点信息类XmlNodeList和API,.SelectNodes()来获得所有节点:

XmlNodeList friendList = root.SelectNodes("Friend")

然后只需要遍历friendList即可。以下展示了两种遍历方式:

void Start()
{
    XmlDocument xml = new XmlDocument();

    XmlNodeList friendList = root.SelectNodes("Friend");

    //遍历方式1
    foreach(XmlNode item in friendList)
    {
        print(item.SelectSingleNode("name").InnerText);
        print(item.SelectSingleNode("age").InnerText);
    }

    //遍历方式2
    for(int i = 0; i < friendList.Count; i++)
    {
        print(friendList[i].SelectSingleNode("name").InnerText);
        print(friendList[i].SelectSingleNode("age").InnerText);
    }
}

三、存储修改Xml文件

(1)决定存储在哪个文件夹下

存储xml文件,在Unity中一定是使用各平台都可读可写可找到的路径

1、Resources 可读,不可写,打包后找不到×

2、Application.streamingAssetsPath 可读,PC可写但ios安卓不可,找得到×

3、Application.dataPath 打包后找不到 ×

4、Application.persistentDataPath 可读可写找得到 √

(2)存储Xml文件

在存储Xml文件之前,我们需要先确定存放路径。我们需要将Xml文件放到Application.persistentDataPath,因此,路径可以为:string path = Application.persistentDataPath + "/PlayerInfo2.xml";("/PlayerInfo2.xml"是自己取的文件名字)

在存储过程中,会用到以下几个类型:XmlDocument 用于创建节点 存储文件;XmlDeclaration 用于添加版本信息;XmlElement 节点类

存储共有5步:

第一步,创建文本对象,也就是之前提到的XmlDocument xml = new XmlDocument();

第二步,添加固定版本信息。也就是添加第一句<?xml version="1.0" encoding="UTF-8"?>。需要用到:XmlDeclaration xmlDec = xml.CreateXmlDeclaration("1.0", "UTF-8", "");创建固定版本信息。其中,第三个参数固定传入空参数,现在不用深究。创建完成后,需要添加到xml对象中:xml.AppendChild(xmlDec);

第三步:添加根节点,使用API,XmlElement root = xml.CreateElement("root");,同样的,xml.AppendChild(root);

第四步:为根节点添加子节点

①添加常见变量

    XmlElement name = xml.CreateElement("name");
    name.InnerText = "Alice";
    root.AppendChild(name);

②添加列表

    XmlElement listInt = xml.CreateElement("listInt");

    for(int i = 0; i < 3; i++)
    {
        XmlElement childNode = xml.CreateElement("int");
        childNode.InnerText = i.ToString();
        listInt.AppendChild(childNode);
    }
    root.AppendChild(listInt);

③添加含属性的对象

    XmlElement itemList = xml.CreateElement("itemList");
    for(int i = 0;i < 3;i++)
    {
        XmlElement childNode = xml.CreateElement("Item");
        childNode.SetAttribute("id", i.ToString());
        childNode.SetAttribute("num", (i * 10).ToString());
        itemList.AppendChild(childNode);
    }
    root.AppendChild(itemList);

5、保存:xml.Save(path);

void Start()
{
    string path = Application.persistentDataPath + "/PlayerInfo2.xml";

    XmlDocument xml = new XmlDocument();

    XmlDeclaration xmlDec = xml.CreateXmlDeclaration("1.0", "UTF-8", "");
    xml.AppendChild(xmlDec);

    //添加根节点
    XmlElement root = xml.CreateElement("root");
    xml.AppendChild(root);

    //为根节点添加子节点
    XmlElement name = xml.CreateElement("name");
    name.InnerText = "Alice";
    root.AppendChild(name);

    XmlElement atk = xml.CreateElement("atk");
    atk.InnerText = "10";
    root.AppendChild(atk);

    XmlElement listInt = xml.CreateElement("listInt");

    for(int i = 0; i < 3; i++)
    {
        XmlElement childNode = xml.CreateElement("int");
        childNode.InnerText = i.ToString();
        listInt.AppendChild(childNode);
    }
    root.AppendChild(listInt);

    XmlElement itemList = xml.CreateElement("itemList");
    for(int i = 0;i < 3;i++)
    {
        XmlElement childNode = xml.CreateElement("Item");
        childNode.SetAttribute("id", i.ToString());
        childNode.SetAttribute("num", (i * 10).ToString());
        itemList.AppendChild(childNode);
    }
    root.AppendChild(itemList);

    //保存
    xml.Save(path);
}

创建完成后,可以在存储路径中找到:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <name>Alice</name>
  <atk>10</atk>
  <listInt>
    <int>0</int>
    <int>1</int>
    <int>2</int>
  </listInt>
  <itemList>
    <Item id="0" num="0" />
    <Item id="1" num="10" />
    <Item id="2" num="20" />
  </itemList>
</root>

(3)修改xml文件

在修改xml文件之前,需要先判断该文件是否存在:File.Exists(path)。判断完成后,直接打开Load xml文件进行修改即可。

Xml文件内节点的删除使用API:root2.RemoveChild(node);

修改或是添加节点只需要像存储一样添加数据/更改数据即可。

void Start()
{
    if(File.Exists(path))
    {
        XmlDocument newXml = new XmlDocument();
        newXml.Load(path);

        XmlNode node = newXml.SelectSingleNode("Root").SelectSingleNode("atk");
        node = newXml.SelectSingleNode("Root/atk");

        XmlNode root2 = newXml.SelectSingleNode("Root");

        root2.RemoveChild(node);
    }

网站公告

今日签到

点亮在社区的每一天
去签到