XML基础

XML基础

XML基础语法

<!--注释-->
其中version代表xml的版本,encoding代表使用的编码格式
xml文件第一行必须要写这个,属于固定格式,第一行必须是这个,注释都不行,这里是有语法错误的

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

xml基本语法

  1. 必须有一个根节点
  2. 标签必须成对出现
  3. 标签之间可以直接包裹数据,也可以包裹标签
  4. xml对大小写敏感
  5. 标签命名应当遵循变量命名规则
  6. 特殊符号应当使用实体引用

<PlayerInfo>
<name>Player</name>
<age>18</age>
<level>20</level>
<itemList>
<item>
<itemName>sword</itemName>
<num>1</num>
</item>
</itemList>
</PlayerInfo>

xml属性

  1. 属性是我们使用xml存储数据时的另一种存储方式

  2. 属性语法,这里我将上面的数据直接复用一下来说明

    <PlayerInfo>
    <name value = “Player”/>
    <age value = “18”/>
    <level value = “20”/>
    <itemList>
    <item itemName = “sword1” num = “1”/>
    <item itemName = “sword2” num = “1”/>
    <item itemName = “sword3” num = “1”/>
    <item itemName = “sword4” num = “1”/>
    </itemList>
    </PlayerInfo>

xml存放位置

  1. 只读不写的xml文件放在Resources或者StreamingAssets文件夹下
  2. 动态存储的xml文件存放在Application.persistentDataPath路径下

C#读取xml文件

  1. XmlDocument(把数据加载到内存中, 方便读取,使用起来也比较简单)
  2. XmlTextReader(以流形式加载,内存占用更小,但是是单向只读,使用不是特别方便,除非有特殊需求,否则不会使用)
  3. Linq

使用XmlDocument读取xml

使用XmlDocument读取xml文件,我们首先需要创建一个文件对象:

XmlDocument xmlDocument = new XmlDocument();

之后我们可以使用XmlDocument的方法来加载xml文件,这里提供两种方式:

  1. 通过Resources加载

    TextAsset textAsset = Resources.Load<TextAsset>("xmlTest");
    xmlDocument.LoadXml(textAsset.text);
    
  2. 通过StreamingAssets加载

    xmlDocument.Load(Application.streamingAssetsPath + @"\xmlTest.xml");
    //输出xml文件对象的xml内容,包括标签
    print(xmlDocument.InnerXml);
    //输出xml文件对象的xml内容,不包括标签
    print(xmlDocument.InnerText);
    

读取xml文件中的节点信息流程:

  1. 获得父节点
  2. 获得子节点
  3. 获得节点信息

首先先来认识两个类:

  1. XmlNode 单个节点信息类
  2. XmlNodeList 多个节点信息类
//获取父节点
XmlNode root = xmlDocument.SelectSingleNode("PlayerInfo");
//获取子节点
XmlNode name = root.SelectSingleNode("name");
//获取子节点信息
print(name.InnerText);
//获取子节点
XmlNode age = root.SelectSingleNode("age");
print(age.InnerText);
//获取子节点的属性内容方式一
print(age.Attributes["value"].InnerText);
//获取子节点的属性内容方式二
print(age.Attributes.GetNamedItem("value").InnerText);

存储xml

存储是写操作,对于需要动态存储的文件我们保存在Application.persistentDataPath目录下。

对比:

  1. Resources:可读,不可写打包之后找不到。
  2. Application.streamingAssetsPath:可读,PC端可写,但移动端不可写。
  3. Application.dataPath:打包之后找不到,此路径常用于测试。
  4. Application.persistentDataPath:可读可写找得到。

存储xml文件要使用的关键类:

  1. XmlDocument:用于创建节点,存储文件。
  2. XmlDeclaration:用于添加版本信息。
  3. XmlElement:节点类。

存储流程:

  1. 创建文本对象。
  2. 添加固定版本信息。
  3. 添加根节点。
  4. 为根节点添加子节点。
  5. 保存。
private void SaveData()
{
    string path = Application.streamingAssetsPath + @"\xmlTest2.xml";
    /*1. 创建文本对象*/
    XmlDocument xml = new XmlDocument();
    /*2. 添加固定信息*/
    //这句代码就相当于是<?xml version="1.0" encoding="UTF-8"?>
    XmlDeclaration xmlD = xml.CreateXmlDeclaration("1.0", "UTF-8", "");
    //创建完成后记得加入xml文本对象中
    xml.AppendChild(xmlD);
    
    /*3. 添加根节点*/
    XmlElement root = xml.CreateElement("Root");
    xml.AppendChild(root);
    /*4. 为根节点添加子节点*/
    XmlElement name = xml.CreateElement("Name");
    name.InnerText = "tian";
    root.AppendChild(name);
    //可以为一个数组或者列表连续添加子节点
    XmlElement intList = xml.CreateElement("intList");
    for (int i = 0; i < 4; i++)
    {
        XmlElement ChildNode = xml.CreateElement("int");
        ChildNode.InnerText = i.ToString();
        intList.AppendChild(ChildNode);
    }
    //记得不要忘了将列表添加到根节点中
    root.AppendChild(intList);
    //添加属性
    XmlElement ItemList = xml.CreateElement("ItemList");
    for (int i = 0; i < 4; 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);
}

修改xml

  1. 先判断是否存在文件。
  2. 加载后直接添加节点或者移除节点即可。

移除节点使用RemoveChild即可。

XML优点

  1. XML是通用规则。
  2. 文件结构清晰易懂。
  3. 容易编辑和理解。
  4. 可用于网络通信交换数据。

XML缺点

  1. 重复工作繁多。
  2. 自定义数据类,需要自己实现具体的功能。且代码重复度高。
  3. 数据容易被修改,只要找到文件位置就可以轻易修改。

主要用途

对于网络游戏:

可以用于存储一些客户端的简单不重要数据。

可以用于传输信息(但不会大范围使用,因为比较耗流量)

对于单机游戏:

用于存储游戏相关数据。

用于配置游戏数据。

XML序列化与反序列化

序列化

什么是序列化?

简单来说把对象转换为可传输的字节序列的过程就叫做序列化,把想逃存储的内容转换为字节序列用于存储或传递。

什么是反序列化?

与序列化的过程相反,将字节序列还原成对象的过程就是反序列化,就是把存储或者收到的字节序列信息解析读取出来使用。

xml序列化准备:

  1. 准备一个数据结构类。
  2. 进行序列化。

进行序列化之前要知道的知识点:

  1. XmlSerializer:用于序列化对象的xml关键类。
  2. StreamWriter:用于存储文件。
  3. using 用于方便资源对象的释放和销毁(资源对象即继承了IDisposable的类)。

序列化步骤:

  1. 确定存储路线。
string path = Application.persistentDataPath + "/xml1.xml";
  1. 结合using写入文件。
public class Item
{
    public int id = 1;
    public int num = 20;
}
public class PlayerInfo2
{
    public string name = "tian";
    public int age = 10;
    public int level = 10;
    public Item item = new Item();
    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("名字是"+name);
        sb.Append("年龄是"+age.ToString());
        sb.Append("等级是"+level.ToString());
        return sb.ToString();
    }
}
public class LoadXml : MonoBehaviour
{
    private void Awake()
    {
        PlayerInfo2 p2 = new PlayerInfo2();
        string path = Application.persistentDataPath + "/xml1.xml";
        //using小括号中为创建的资源对象,当using语句块执行完后就会调用资源对象的Dispose方法来释放资源对象。
        //StreamWriter需要传入一个路径,这样才知道要往那个位置去写。
        using (StreamWriter sw = new StreamWriter(path))
        {
            //创建xml序列化对象,参数需要传入要序列化的类型。
            XmlSerializer xs = new XmlSerializer(typeof(PlayerInfo2));
            //序列化,第一个参数是使用哪个流对象,第二个参数是序列化那个实例。
            xs.Serialize(sw, p2);
        }
        print(path);
    }
}

xml序列化的一些缺点

  1. 只能存public,不支持字典序列化

自定义xml信息

  1. 设置节点名字[XmlElement(名字)]
  2. 设置属性和属性名字[XmlAtribute(名字)]
  3. 设置数组和数组项名字
    1. 设置数组的名字[XmlArray(名字)]
    2. 设置数组项的名字[XmlArrayItem(名字)]

反序列化

反序列化的流程:

  1. 判断文件是否存在使用File. Exists(path)方法。
  2. 如果存在就读取文件。

关键知识点:

  1. using语句块
  2. StreamReader
  3. XmlSerializer

读取文件的书写思路与写入文件一致:

private void DeserializeTest()
{
    string path = Application.persistentDataPath + "/xml1.xml";
    if (File.Exists(path))
    {
        using (StreamReader sr = new StreamReader(path))
        {
            XmlSerializer xs = new XmlSerializer(typeof(PlayerInfo2));
            //将得到的信息转换成对应的数据结构
            PlayerInfo2 p2 = xs.Deserialize(sr) as PlayerInfo2;
        
        } 
    }
}

注意:List对象如果有默认值反序列化时不会清空重新加,而是会往后继续添加。

IXmlSerializable接口

IXmlSerializable是干什么的?

C#为XmlSerializer提供了可拓展内容。可以让一些不能被序列化和反序列化的特殊类也可以被处理,比如字典,只需让特殊类实现此接口即可。

此接口需要实现的方法:

//返回结构,返回null即可
public XmlSchema GetSchema()
{
    return null;
}
/// <summary>
///反序列化时会调用的方法
/// </summary>
/// <param name="reader"></param>
public void ReadXml(XmlReader reader)
{
    //在里面可以自定义反序列化的规则,但要使用XmlReader这个参数类
}
/// <summary>
/// 序列化时会自动调用的方法
/// </summary>
/// <param name="writer"></param>
public void WriteXml(XmlWriter writer)
{
    //在里面可以自定义序列化的规则,但是要使用XmlWriter这个参数类
}
操作属性

写属性:

/// <summary>
/// 当序列化此类时就会按照这里的规则来序列化
/// </summary>
/// <param name="writer"></param>
public void WriteXml(XmlWriter writer)
{
    writer.WriteAttributeString("age", this.age.ToString());
}

读属性:

/// <summary>
/// 当反序列化此类时就会按照这里的规则来反序列化
/// </summary>
/// <param name="reader"></param>
public void ReadXml(XmlReader reader)
{
    this.age = int.Parse(reader["age"]);
}
操作节点

写节点:

/// <summary>
/// 当序列化此类时就会按照这里的规则来序列化
/// </summary>
/// <param name="writer"></param>
public void WriteXml(XmlWriter writer)
{
    writer.WriteElementString("age", this.age.ToString());
}

读节点:

/// <summary>
/// 当反序列化此类时就会按照这里的规则来反序列化
/// </summary>
/// <param name="reader"></param>
public void ReadXml(XmlReader reader)
{
    //由于节点读取比较特殊,使用reader.Read()每次只会向后读取一个标签,所以我们需要使用循环来读取我们想要的信息
    while (reader.NodeType == XmlNodeType.Element)
    {
        //每当读取到信息后我们需要用switch来判断不同的信息有不同的赋值方式。
        switch (reader.Name)
        {
            case "age":
                reader.Read();
                this.age = int.Parse(reader.Value);
                break;
        }
    }
}
包裹节点

写包裹节点:

/// <summary>
/// 当序列化此类时就会按照这里的规则来序列化
/// </summary>
/// <param name="writer"></param>
public void WriteXml(XmlWriter writer)
{
    XmlSerializer xs = new XmlSerializer(typeof(int));
    //start和End一定要成对出现
    writer.WriteStartElement("age");
    xs.Serialize(writer, age);
    writer.WriteEndElement();
}

读包裹节点:

/// <summary>
/// 当反序列化此类时就会按照这里的规则来反序列化
/// </summary>
/// <param name="reader"></param>
public void ReadXml(XmlReader reader)
{
    XmlSerializer xs = new XmlSerializer(typeof(int));
    //跳过根节点
    reader.Read();
    //start和End一定要成对出现
    reader.ReadStartElement("age");
    age = (int)xs.Deserialize(reader);
    reader.ReadEndElement();
}

让Dictionary支持序列化和反序列化

想让Dictionary支持xml序列化和反序列化的会有一个问题:

我们没有办法修改C#自带的类。

解决方案:重写一个Dictionary类并让这个类继承Dictionary和实现IXmlSerializable接口。

using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace CsharpBaseModule.SaveData.Xml
{
    public class SerialiazedDictionary<TKey, TValue> : Dictionary<TKey,TValue>, IXmlSerializable
    {
        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            XmlSerializer keySer = new XmlSerializer(typeof(TKey));
            XmlSerializer valueSer = new XmlSerializer(typeof(TValue));

            //要跳过根节点
            reader.Read();
            //判断 当前不是元素节点 结束 就进行 反序列化
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                //反序列化键
                TKey key = (TKey)keySer.Deserialize(reader);
                //反序列化值
                TValue value = (TValue)valueSer.Deserialize(reader);
                //存储到字典中
                this.Add(key, value);
            } 
        }

        public void WriteXml(XmlWriter writer)
        {
            XmlSerializer keySer = new XmlSerializer(typeof(TKey));
            XmlSerializer valueSer = new XmlSerializer(typeof(TValue));

            foreach (KeyValuePair<TKey, TValue> kv in this)
            {
                //键值对 的序列化
                keySer.Serialize(writer, kv.Key);
                valueSer.Serialize(writer, kv.Value);
            }
        }
    }  
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring MVC中,可以使用web.xml文件进行基础配置。下面是一个示例的web.xml配置文件: ```xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>Spring MVC Application</display-name> <!-- 配置DispatcherServlet --> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/springmvc-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- 映射DispatcherServlet的URL --> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> ``` 在上面的配置中,我们首先定义了一个名为`dispatcher`的Servlet,并指定了它的类为`org.springframework.web.servlet.DispatcherServlet`。然后,我们通过`init-param`元素指定了Spring MVC配置文件的位置,这里是`/WEB-INF/springmvc-servlet.xml`。最后,我们使用`servlet-mapping`元素将`dispatcher`Servlet映射到根路径`/`。 需要注意的是,上述配置中的`/WEB-INF/springmvc-servlet.xml`是Spring MVC的配置文件,用于定义控制器、视图解析器等相关配置。你可以根据自己的需求进行配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值