kizumi_header_banner_img

Hello! Beautiful Kizumi!

加载中

文章导读

数据持久化之XML


avatar
Yuyas 2025年6月14日 5

数据持久化之XML

1.固定内容

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

2.注释

<!--content-->

3.基本语法

<PlayerInfo>
   <name>沈11</name>
   <age>18</age>
   <sex>true</sex>
   <ItemList>
       <Item>
           <id>1</id>
           <num>10</num>
       </Item>
       <Item>
           <id>2</id>
           <num>10</num>
       </Item>
   </ItemList>
</PlayerInfo>

4.基本规则

  • 每个元素必须有关闭标签
  • 元素命名规则与C#一致
  • 必须有根元素
  • 特殊符号需要替换

&lt 对应 <
&gt 对应 >
&amp 对应 &
&apos 对应 '
&quot 对应 "

5.属性

<itemList>
<Item id = "1" num = "10"/>
<Item id = "2" num = "20"/>
<Item id = "3" num = "30"/>
</itemList>

XML读取

C#读取XML的方法有几种

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

1.读取XML文件

  • XmlDocument xml = new XmlDocument();
  • 读取文本方式1-xml.LoadXml(传入xml文本字符串)
  • 读取文本方式2-xml.Load(传入路径)XmlDocument xml = new XmlDocument();
    // 1.通过文本加载xml
    TextAsset textAsset = Resources.Load<TextAsset>(“TestXml”);
    xml.LoadXml(textAsset.text);
    // 2.通过文件加载xml
    xml.Load(Application.streamingAssetsPath + “/TestXml.xml”);

2.读取元素和属性

  • 获取单个节点: XmlNode node = xml.SelectSingleNode(节点名)
  • 获取多个节点: XmlNodeList nodeList = xml.SelectNodes(节点名)//获取xml当中的根节点
    XmlNode root = xml.SelectSingleNode(“Root”);
    //再通过根节点 去获取下面的子节点
    XmlNode nodeName = root.SelectSingleNode(“name”);
    //如果想要获取节点包裹的元素信息 直接 .InnerText
    print(nodeName.InnerText);

    XmlNode nodeAge = root.SelectSingleNode(“age”);
    print(nodeAge.InnerText);

    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);

    //这里是获取 一个节点下的同名节点的方法
    XmlNodeList friendList = root.SelectNodes(“Friend”);

存储XML

注意:存储xml文件 在Unity中一定是使用各平台都可读可写可找到的路径 1.Resources 可读 不可写 打包后找不到 × 2.Application.streamingAssetsPath 可读 PC端可写 找得到 × 3.Application.dataPath 打包后找不到 × 4.Application.persistentDataPath 可读可写找得到 √

关键类 XmlDocument 用于创建节点 存储文件 关键类 XmlDeclaration 用于添加版本信息 关键类 XmlElement 节点类

//存储有5步
//1.创建文本对象
XmlDocument xml = new XmlDocument();

//2.添加固定版本信息
//这一句代码 相当于就是创建<?xml version="1.0" encoding="UTF-8"?>这句内容
XmlDeclaration xmlDec = xml.CreateXmlDeclaration("1.0", "UTF-8", "");
//创建完成过后 要添加进入 文本对象中
xml.AppendChild(xmlDec);

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

//4.为根节点添加子节点
//加了一个 name子节点
XmlElement name = xml.CreateElement("name");
name.InnerText = "唐老狮";
root.AppendChild(name);

保存Xml

Xml.Save(path);

删除节点

root.RemoveChild(node);

XmlNode和XmlElement区别

当元素没有值的时候就可以用XmlNode

需要赋值就用XmlElement(InnerText,SetAttribute / GetAttribute,TagName)

Xml序列化

string path = Application.persistentDataPath + "/Lesson1Test.xml";
using ( StreamWriter stream = new StreamWriter(path) )
{
XmlSerializer s = new XmlSerializer(typeof(Lesson1Test)); // 决定序列化翻译机器的类型
// 文件写入流,序列化对象
s.Serialize(stream, lt);
}

using的作用是代码块运行完毕后,自动调用Dispose()销毁StreamWriter

注意: 1.只能序列化公共成员public 2.不支持字典Dictionary序列化 3.可以通过特性修改节点信息 或者设置属性信息 [XmlAttribute(“Test1”)](不设置此特性默认为节点存储的Xml) 4.Stream相关要配合using使用

Xml反序列化

// 需要进行判空
if( File.Exists(path) )
{
using (StreamReader reader = new StreamReader(path))
{
XmlSerializer s = new XmlSerializer(typeof(Lesson1Test));
Lesson1Test lt = s.Deserialize(reader) as Lesson1Test;
}
}

注意:List对象 如果有默认值 反序列化时 不会清空 会往后面添加

IXmlSerializable接口(自定义序列化读写)

public class TestLesson3 : IXmlSerializable
{
public int test1 = 10;
public int test2 = 99;

public XmlSchema GetSchema()
{
return null;
}

public void ReadXml(XmlReader reader)
{
// 三种读取方式

// 1.读属性
test1 = int.Parse(reader["Test1"]);
test2 = int.Parse(reader["Test2"]);

// 2.读节点
// 方式一
reader.Read();//这时读到的是节点
reader.Read();//这时读到的才是值
test1 = int.Parse(reader.Value);//得到值内容
reader.Read();//得到节点尾部配对
reader.Read();//读到节点开头
reader.Read();//读到值
test2 = int.Parse(reader.Value);//获取值内容

// 方式二
while (reader.Read())
{
if(reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "Test1":
reader.Read();
test1 = int.Parse(reader.Value) ;
break;
case "Test2":
reader.Read();
test2 = int.Parse(reader.Value);
break;
}
}
}

// 3.读包裹点
XmlSerializer s = new XmlSerializer(typeof(int));
reader.Read();
reader.ReadStartElement("Test1");
test1 = (int)s.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("Test2");
test1 = (int)s.Deserialize(reader);
reader.ReadEndElement();
}

public void WriteXml(XmlWriter writer)
{
// 三种方式

// 1.写属性
writer.WriteAttributeString("Test1", test1.ToString());
writer.WriteAttributeString("Test2", test2.ToString());

// 2.写节点
writer.WriteElementString("Test1", test1.ToString());
writer.WriteElementString("Test2", test2.ToString());

// 3.写包裹节点
XmlSerializer s = new XmlSerializer(typeof(int));
writer.WriteStartElement("Test1");
s.Serialize(writer, test1);
writer.WriteEndElement();

writer.WriteStartElement("Test2");
s.Serialize(writer, test2);
writer.WriteEndElement();

}
}

自定义可Xml序列化的Dictionary示例

public class SerializeDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
   public XmlSchema GetSchema()
  {
       return null;
  }

   public void ReadXml(XmlReader reader)
  {
       reader.Read();

       XmlSerializer s1 = new XmlSerializer(typeof(TKey));
       XmlSerializer s2 = new XmlSerializer(typeof(TValue));

       while (reader.NodeType != XmlNodeType.EndElement)
      {
           TKey key = (TKey)s1.Deserialize(reader);
           TValue value = (TValue)s2.Deserialize(reader);
           this.Add(key, value);
      }

       reader.Read();
  }

   public void WriteXml(XmlWriter writer)
  {
       XmlSerializer s1 = new XmlSerializer(typeof(TKey));
       XmlSerializer s2 = new XmlSerializer(typeof(TValue));

       foreach(KeyValuePair<TKey,TValue> pair in this)
      {
           s1.Serialize(writer, pair.Key);
           s2.Serialize(writer, pair.Value);
      }
  }
}



评论(0)

查看评论列表

暂无评论


发表评论

表情 颜文字
插入代码

个人信息

avatar

24
文章
1
评论
1
用户

近期文章