快速入门C#中XML文件操作

最近在用XML做游戏关卡存档使用了XML,之前有过一次整理,但是发现整理的有点垃圾,索性这次一次将这一块的知识点重新整理一遍,方便快速入门


XML文件说明
<!-- -->
<!-- 单行注释 -->

<!--
xml对大小写敏感
名称不能以数字或标点开始
也不能以xml、Xml、XML开始
不能有空格
-->
<!-- 必须要写节点声明,一般值为这个 -->
<?xml version="1.0" encoding="utf-8" ?>
<!--xml文件必须有一个根节点,且只有一个根-->
<root>
    <subchild data = "2022">
        元素
    </subchild>
</root>


<!--标签的属性必须加"",属性值是某个标签的附加属性-->
<root data = "2022年"> </root>

<!-- 单标签(单节点)下面两个是相同的 -->
<root />
<root></root>

<!--可以存在同名标签-->
<root>
    <child></child>
    <child></child>
</root>

xml的实体引用(特殊转义)

实体引用[还要加个;]代表
&lt;<
&gt;>
&amp;&
&apos;
&quot;"
<!-- 错误写法 -->
<test>1 < 2 </test>
<!-- 正确写法 -->
<test>1 &lt; 2 </test>
XML操作
常见节点说明

常见节点有:XmlNode,XmlAttribute,XmlElement,XmlDocument,XmlDeclaration;所有的节点都是从XmlNode继承下来;XmlElement和XmlDeclaration有些相似是继承XmlLinkedNode,XmlLinkedNode是继承XmlNode,看名字就知道类似模拟链表的操作(像但不是)

XmlNode

在Xml文档中表示单个节点

属性

  • Attributes 当前节点的所有属性(可以通过名称,或者所属下标位置来访问)
  • ChildNodes 返回所有的子节点
  • FirstChild 第一个子节点
  • HasChildNodes 是否有子节点
  • LastChild 最后一个子节点
  • InnerText 获取或设置当前节点的内容(元素);元素以字符串形式传入,会转义
  • InnerXml 获取或设置当前节点的内容(元素);元素以xml形式传入
  • this.[string] 查找第一个名称符合的子节点
  • Name 返回当前节点的限定名称(命名空间+LocalName)(如果没有命名空间则与LocalName一样)
  • LocalName 返回当前节点的本地名称
  • NextSibling 返回同级下一个兄弟节点
  • OutXml 获取包含当前节点的内容以Xml形式返回
  • OwnerDocument 获取所属的Document
  • ParentNode 获取当前节点的父节点
  • PreviousSibling 返回同级的上一个兄弟节点
  • Value 返回当前节点的值;和InnerText很像但是对于不同节点类型有不同的返回结果;
    • Element 返回null,使用InnerText代替
    • Attribute 返回属性的内容
  • NodeType 返回当前节点的类型
  • Prefix 返回或设置此节点的命名空间前缀

方法

  • AppendChild(XmlNode) 将指定节点添加到此节点的子节点末尾
  • Clone() 创建此节点的副本,包括子树相当于调用CloneNode(true)
  • CloneNode(bool) 创建此节点的副本,参数为true时克隆此节点下的子树,false时仅克隆节点本身
  • InsertAfter(XmlNode A,XmlNode B) 将A节点插入到B节点后面;不允许B是A的子节点,A,B是不同文档(Document)创建的;
  • InsertBefore(XmlNode A,XmlNode B) 将A节点插入到B节点前面面;不允许B是A的子节点,A,B是不同文档(Document)创建的;
  • PrependChild(XmlNode) 将指定节点添加的此节的子节点表头
  • RemoveAll() 移除当前节点的所有子节点和属性
  • RemoveChild(XmlNode) 删除指定的子节点
  • ReplaceChild(XmlNode new,XmlNode old) 将old替换成new【tip:old必须是该节点的子节点,不能是孙节点或更深】
  • SelectNodes(String) 查找与XPath表达式匹配的节点列表。
  • SelectSingleNode(String) 查找与XPath表达式匹配的第一个节点
  • WriteContentTo(XmlWriter) 将节点的所有子节点保存到指定的XmlWriter(内容等效 InnerXml)
  • WriteTo(XmlWriter) 将当前节点保存到指定的(内容等效 OuterXml)
XmlDocument

表示 XML 文档。 可使用此类在文档中加载、验证、编辑、添加和放置 XML。

属性

  • DocumentElement 获取Xml文档树的根,不存在返回null(与FirstChild不同,FirstChild会获取到Xml的DOCTYPE声明,但是可以用LastChild代替获取根,因为根只能有一个)
  • DocumentType 获取包含 DOCTYPE 声明的节点
  • PreserveWhitespace 获取或设置一个值,该值指示是否在元素内容中保留空白区域。
    • 在Load前为true,则保留文本的格式;为false时会则保留有效的空白(父子节点之间是两个空格的缩进)
    • 在Save前为true,则文档中的空白将保留在输出中;为false时会自动缩进输出

方法

  • CreateAttribute(String) 创建具有指定Name的XmlAtrribute
  • CreateElement(String) 创建具有指定Name的XmlElement
  • CreateXmlDeclaration(String version , String encoding, String standalone) 创建XmlDeclaration,version必须是“1.0”,encoding建议是“UTF-8”,standalone建议填“”或者String.Empty
  • GetElementById(String) 获取具有指定 ID 的XmlElement(操作有点麻烦,不考虑)
  • GetElementsByTagName(String) 返回一个XmlNodeList,包含所有节点名称与Name匹配的所有子元素;
  • Load(String) 从指定的 URL 加载 XML 文档;还有很多加载的,略
  • LoadXml(String) 从指定的字符串加载 XML 文档
  • Save(String) 将 XML 文档保存到指定的文件。 如果存在指定文件,则此方法会覆盖它;还有很多保存的,略
XmlDeclaration

表示 XML 声明节点 <?xml version='1.0'...?>。

大部分都有,略

XmlElement

表示元素

属性

  • HasAttributes 是否有任何属性
  • IsEmpty 获取或设置元素的标记格式;为true时,格式为 ;为false时,或者有内容在里面;主动设置ture时会以短标记

方法

  • GetAttribute(string) 返回具有指定名称的属性的值
  • GetAttributeNode(String) 返回具有指定名称的XmlAttribute
  • GetElementsByTagName(String) 返回一个XmlNodeList,包含所有节点名称与Name匹配的所有子元素;
  • HasAttribute(String) 确定当前节点是否具有带有指定名称的属性
  • RemoveAll() 移除当前节点的所有子节点和属性
  • RemoveAllAttributes() 从元素中删除所有指定的属性(只针对当前节点,子节点不受影响)
  • RemoveAttribute(String) 按名称删除指定属性
  • RemoveAttributeAt(int) 按索引删除指定属性
  • RemoveAttributeNode(XmlAttribute) 通过XmlAttribute来删除指定属性
  • SetAttribute(String name, String value) 设置具有指定名称的属性的值
  • SetAttributeNode(XmlAttribute) 添加指定的XmlAttribute
XmlAttribute

表示属性

属性

  • Prefix 返回或设置此节点的命名空间前缀
  • Value 返回或设置属性的值

方法

基本上用不到方法,略

XML输入输出流
XmlReader

表示提供对 XML 数据进行快速、非缓存、只进访问的读取器。

XmlReader reader = XmlReader.Create(string path);	// 创建读取器实例
reader.Read(); reader.ReadAsync();	// 读取器读取下一个节点(同步,异步);当读取不到时返回false
reader.NodeType;	// 当前节点类型
reader.Name;		// 当前节点名称
reader.Value;		// 当前节点内容
reader.Close();		// 关闭实例
<book>123</book>
对于一个节点分为:
XmlNodeType.Element(<book>)
XmlNodeType.Text(123)
XmlNodeType.EndElement(</book>)
所以reader.Read();时候是一个一个读
XmlWriter

表示一个写入器,该写入器提供一种快速、非缓存和只进方式以生成包含 XML 数据的流或文件。

XmlDocument xmlDoc = new XmlDocument();
var root = xmlDoc.CreateElement("root");
xmlDoc.AppendChild(root);
for(int i = 1; i < 6; i++) {
    var child = root.OwnerDocument.CreateElement("item");
    root.AppendChild(child);
    child.InnerText = i.ToString();
}
XmlWriterSettings settings = new XmlWriterSettings();   // 创建写入器的设置
settings.Indent = true;
settings.IndentChars = "\t";
settings.Encoding = System.Text.Encoding.UTF8;
using (XmlWriter writer = XmlWriter.Create(folderFullPath + "/Test2.xml", settings)) {
    xmlDoc.Save(writer);    // 将xmldoc保存到指定的写入器中
}

XmlWriterSetting

属性内容默认值
Encoding使用的文本编码utf-8
Indent是否缩进元素flase(无缩进)
IndentChars缩进时使用的字符串两个空格
NewLineChars用于换行的字符串\r\n
OmitXmlDeclaration隐藏XML声明(抬头有版本和文本编码的声明)false(不隐藏)
案例
// 自己生成
XmlDocument xmlDoc = new XmlDocument(); // 创建文档

xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null));  // 添加声明
XmlElement root = xmlDoc.CreateElement("root"); // 创建节点(根)
xmlDoc.AppendChild(root);	// 添加到末尾
for (int i = 1; i <= 5; i++) {
    XmlElement child = xmlDoc.CreateElement("Book");
    root.AppendChild(child);
    child.SetAttribute("id", i.ToString()); // 设置属性
    child.InnerText = i.ToString();     // 设置内容
}

xmlDoc.Save(Console.Out);		// 保存到输出窗口
// 自己加载
XmlDocument xmlDoc1 = new XmlDocument();
xmlDoc1.Load(folderFullPath + "/Test.xml");     // 指定文件加载

string xml = File.ReadAllText(folderFullPath + "/Test.xml");
XmlDocument xmlDoc2 = new XmlDocument();
xmlDoc2.LoadXml(xml);       // xml字符串加载
XPath

XPath 使用路径表达式来选取 XML 文档中的节点或节点集

语法
例子
<?xml version="1.0" encoding="UTF-8"?>
<root>
	<skill name="普通攻击">轻轻的一击</skill>
	<skill name="重击">沉重的一击</skill>
	<skill name="必杀技">致命一击,大量伤害</skill>
	<child name = "child1">
		<name>1</name>
	</child>
	<child>
		<name>2</name>
		<cchild name = "child2">
			<name>3</name>
		</cchild>
	</child>
	<book>
		<name>4</name>
	</book>
</root>
选取节点
表达式描述
nodename选取此节点的所有(叫nodename)子节点
/从根节点选取(取子节点)
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置(取子孙节点)。
.选取当前节点
选取当前节点的父节点
@选取属性
路径表达结果
skill(从root出发)得到root所有叫skill的子节点
/root/child/name从文档出发找到所有name节点的绝对路径满足这个(结果1,2都有)
注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
child/name从当前节点开始,选取所有child节点中的所有name节点(相对路径)
//name选取所有name节点,而不管它们在文档中的位置(与当前节点无关)
root/child//name选取所有root子节点中的所有child节点下的所以name节点(不管在child之下的位置)(比上面的查找全部name,这个是查找child下的所有name)
//@name选取名为 name 的所有属性
root/skill/@name查找到所有root/skill节点所有名为 name 的所有属性
谓语

谓语用来查找某个特定的节点或者包含某个指定的值的节点

表达式结果
root/skill[1]选取root子节点第一个skill(下标是从1开始)
root/skill[last()]选取root子节点最后个skill
root/skill[last()-1]选取root子节点倒数第二个skill
root/skill[position()<=2]选取root子节点最前面的两个skill(判断符号 <,<=,=,>,>=,!= 除了等于比较特殊)
//skill[@name]选取所有拥有名为 name 的属性的 skill元素。
root/skill[@name = ‘重击’]选取所有拥有名为 name属性为重击 的 skill元素。
root/child[name > 1]选取所有root节点中所有child节点,且name节点的值大于1(值为数值的时候才能比较)
选取未知
通配符描述
*匹配任何元素节点
@*匹配任何属性节点
表达式结果
/root/*选取root下所有子元素
//*选取当前节点下的所有节点(以递归的顺序将所有节点输出)
//child[@*]选取所有带属性的child节点
选取若干

使用 | 来去若干

表达式结果
/root/skill | /root/child/name选取root/skill和root/child/name
运算符
运算符描述实例返回值
|计算两个节点集//book | //cd返回所有拥有 book 和 cd 元素的节点集
+加法6 + 410
-减法6 - 42
*乘法6 * 424
div除法8 div 42
=等于price=9.80如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 false。
!=不等于price!=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
<小于price<9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
<=小于或等于price<=9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
>大于price>9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
>=大于或等于price>=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 false。
orprice=9.80 or price=9.70如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。
andprice>9.00 and price<9.90如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。
mod计算除法的余数5 mod 21

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个人心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值