Unity:XML笔记
写在前面:
写本系列(自用)的目的是回顾已经学过的知识、记录新学习的知识或是记录心得理解,方便自己以后快速复习,减少遗忘。
一、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>
特殊的符号应该用实体引用
< 小于 : <
> 大于 :>
&和 : &
' 单引号 :&apos
" 引号 :"
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");//遍历方式1foreach(XmlNode item in friendList){print(item.SelectSingleNode("name").InnerText);print(item.SelectSingleNode("age").InnerText);}//遍历方式2for(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);}