零、文章目录
XML详解
1、XML是什么
- XML(Extensible Markup Language)是一种用于存储和传输数据的标记语言。它由万维网联盟(W3C)开发。
- XML被广泛用于数据交换、数据存储、Web服务、网络协议(如SOAP)等方面。它是一种非常流行的数据格式,在Web开发中扮演着重要角色。
- XML与HTML类似,但XML更加灵活和可扩展,它允许开发人员创建自己的标记,而不是只限于HTML中预定义的标记。
- XML的主要特点包括:
- 可扩展性:XML允许开发人员创建自定义的标记和元素,以表示数据和结构,这使得XML可以用于多种应用程序和领域。
- 结构化:XML文档由嵌套的元素和属性组成,这使得XML可以表示复杂的数据结构。
- 标准化:XML支持标准化的字符编码,如UTF-8和UTF-16,这使得XML可以在不同的平台和应用程序之间进行交换和处理。
- 简单易读:XML文档具有清晰的层次结构和良好的可读性,这使得XML易于编写和理解。
2、XML文档基本结构
(1)XML声明
- 每个XML文档都必须包含一个声明,它描述了XML文档的版本和编码方式。例如,在以下的XML文档中,声明了XML版本1.0,编码方式为UTF-8
<?xml version="1.0" encoding="UTF-8"?>
(2)根元素
- XML文档必须有一个根元素,它包含了所有其他元素。根元素通常是所有其他元素的父元素。例如,在以下的XML文档中,
<根元素>
是根元素
<根元素>
<!-- 其他元素 -->
</根元素>
(3)元素
- 元素是XML文档的基本单位,它包含文本或其他元素。元素通过标签来标识,例如,以下的XML文档中,
<p>
和</p>
是段落元素的开始和结束标签
<p>这是一个段落。</p>
(4)属性
- 属性是元素的附加信息,它们提供了关于元素的额外信息。属性在开始标签中定义,并以名称/值对的形式出现。例如,以下的XML文档中,
href
是链接元素的属性,值为一个URL:
<a href="">这是一个链接</a>
(5)注释
- 注释用于在XML文档中添加注释和说明。注释以
<!--
开始,以-->
结束。例如,以下的XML文档中,<!-- 这是一个注释 -->
是一个注释:
<!-- 这是一个注释 -->
(6)处理指令
- 处理指令提供了关于XML处理器如何处理文档的指令。例如,以下的XML文档中,
<?xml-stylesheet ... ?>
是一个处理指令,它指定了一个与XML文档关联的样式表:
<?xml-stylesheet type="text/xsl" href=""?>
(7)命名空间
-
命名空间:一个用于定义XML文档中元素和属性的范围和作用域的机制。它允许在XML文档中定义多个不同的命名空间,以便将元素和属性限制在特定的范围内。
-
在XML中,命名空间被定义为一个URI(统一资源标识符),它为XML元素提供一个唯一的名称。命名空间可以用于区分具有相同名称的元素或属性,使用命名空间可以帮助避免名称冲突。
-
在XML文档中,命名空间可以用以下两种方式定义:
- 在元素上定义命名空间:可以在XML文档的根元素或特定元素上使用命名空间属性来定义命名空间。例如:
<root> <element xmlns="/"></element> </root>
- 使用XML命名空间前缀:可以使用XML命名空间前缀来定义命名空间,并指定其URI。例如:
<root xmlns:ns=""> <ns:element>Value</ns:element> </root>
-
多个命名空间示例如下
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:ns1="/namespace1"
xmlns:ns2="/namespace2">
<ns1:element1>Value 1</ns1:element1>
<ns2:element2>Value 2</ns2:element2>
</root>
3、C#对xml文件结构的抽象
- XML 文档被抽象为一个
XmlDocument
对象,该对象包含了整个 XML 文档的内容。XmlDocument
对象可以通过XmlReader
或XmlWriter
类来读取或写入 XML 文件。 - XML 文档中的元素被抽象为
XmlElement
对象,这些对象包含了元素的名称、属性和子元素。开发人员可以通过XmlElement
对象的属性来访问元素的名称、属性和子元素。 - XML 文档中的属性被抽象为
XmlAttribute
对象,这些对象包含了属性的名称和值。开发人员可以通过XmlAttribute
对象的属性来访问属性的名称和值。 - XML 文档中的文本内容被抽象为
XmlText
对象,这些对象包含了文本内容。开发人员可以通过XmlText
对象的属性来访问文本内容。 - 一些其他的类和接口,如
XmlNodeList
、XmlNodeReader
、XmlNodeWriter
等,用于处理 XML 文档中的节点列表、读取和写入 XML 节点等。 - 这些类都在命名空间
下面。
4、C#对xml文档的增删改查
(1)创建一个XML文件
//创建xml文档
XmlDocument xmldoc = new XmlDocument();
//加入XML声明
XmlDeclaration xmldecl = ("1.0", "UTF-8", null);
(xmldecl);
// 创建一个注释节点
XmlNode comment = ("这是一个注释");
(comment);
//加入一个根元素
XmlElement employees = ("Employees");
(employees);
//根元素加入一些子元素
for (int i = 1; i < 5; i++)
{
// 创建一个注释节点
XmlNode comment1 = ("Employee" + i);
(comment1);
XmlElement employee = ("Employee"+i);//创建一个子节点
("name", "人员" + i);//设置该节点属性
XmlElement age = ("Age");//创建一个孙节点
= (18+i).ToString();//设置文本
(age);//添加到子节点中
XmlElement sex = ("Sex");//创建一个孙节点
= i % 2 == 0 ? "男" : "女";//设置文本
(sex);//添加到子节点中
XmlElement salary = ("Salary");
= (10000 + i * 100).ToString();
(salary);
(employee);//将子节点添加到根节点中
}
//保存创建好的XML文档
("");
- 生成的文件内容如下
<?xml version="1.0" encoding="UTF-8"?>
<!--这是一个注释-->
<Employees>
<!--Employee1-->
<Employee1 name="人员1">
<Age>19</Age>
<Sex>女</Sex>
<Salary>10100</Salary>
</Employee1>
<!--Employee2-->
<Employee2 name="人员2">
<Age>20</Age>
<Sex>男</Sex>
<Salary>10200</Salary>
</Employee2>
<!--Employee3-->
<Employee3 name="人员3">
<Age>21</Age>
<Sex>女</Sex>
<Salary>10300</Salary>
</Employee3>
<!--Employee4-->
<Employee4 name="人员4">
<Age>22</Age>
<Sex>男</Sex>
<Salary>10400</Salary>
</Employee4>
</Employees>
(2)读取XML文件内容
//创建xml文档
XmlDocument xmldoc = new XmlDocument();
//导入指定xml文件
XmlReaderSettings settings = new XmlReaderSettings();
= true;//忽略文档里面的注释,注释也是节点,但是无法转换成XmlElement,所以这里不忽略,下面转换就报错
//XmlReader是用liu需要using包起来,读完释放资源,防止占用
using (XmlReader reader = ("", settings))
{
(reader);
}
//获取根节点
XmlElement employees=;
//遍历根节点的子节点
foreach (XmlElement employee in )
{
StringBuilder sb = new StringBuilder();
($"{}--{("name")}");
foreach (XmlElement child in )
{
($"--{}:{}");
}
(());
}
- 读取内容如下
Employee1--人员1--Age:19--Sex:女--Salary:10100
Employee2--人员2--Age:20--Sex:男--Salary:10200
Employee3--人员3--Age:21--Sex:女--Salary:10300
Employee4--人员4--Age:22--Sex:男--Salary:10400
(3)修改XML文件内容
//创建xml文档
XmlDocument xmldoc = new XmlDocument();
//导入指定xml文件
("");
//获取根节点
XmlElement employees = ;
//添加节点
XmlElement newemployee = ("Employee4");//创建一个子节点
("name", "新的人员4");//设置该节点属性
XmlElement age = ("Age");//创建一个孙节点
= "88";//设置文本
(age);//添加到子节点中
XmlElement sex = ("Sex");//创建一个孙节点
="女博士";//设置文本
(sex);//添加到子节点中
XmlElement salary = ("Salary");
= "20000";
(salary);
(newemployee, [1]);//将子节点添加到第1个节点后
//删除节点
XmlNode nodeDelete=("//Employee1");//筛选匹配的第一个节点
(nodeDelete);//删除筛选出来的节点
//修改节点
XmlElement nodeUpdate = ("//Employee2") as XmlElement;//筛选匹配的第一个节点
("name", "新的人员2");
nodeUpdate["Age"].InnerText = "99";
nodeUpdate["Sex"].InnerText = "男博士";
nodeUpdate["Salary"].InnerText = "18888";
//筛选多个节点
XmlNodeList nodes= ("//Employee4");
("打印筛选出的节点信息");
foreach (XmlElement employee in nodes)
{
StringBuilder sb = new StringBuilder();
($"{}--{("name")}");
foreach (XmlElement child in )
{
($"--{}:{}");
}
(());
}
//保存创建好的XML文档
("");
();
("打印修改后的结果");
((""));
- 运行效果
打印筛选出的节点信息
Employee4--新的人员4--Age:88--Sex:女博士--Salary:20000
Employee4--人员4--Age:22--Sex:男--Salary:10400
打印修改后的结果
<?xml version="1.0" encoding="UTF-8"?>
<!--这是一个注释-->
<Employees>
<!--Employee1-->
<Employee4 name="新的人员4">
<Age>88</Age>
<Sex>女博士</Sex>
<Salary>20000</Salary>
</Employee4>
<!--Employee2-->
<Employee2 name="新的人员2">
<Age>99</Age>
<Sex>男博士</Sex>
<Salary>18888</Salary>
</Employee2>
<!--Employee3-->
<Employee3 name="人员3">
<Age>21</Age>
<Sex>女</Sex>
<Salary>10300</Salary>
</Employee3>
<!--Employee4-->
<Employee4 name="人员4">
<Age>22</Age>
<Sex>男</Sex>
<Salary>10400</Salary>
</Employee4>
</Employees>
(4)多命名空间XML操作
//创建xml文档
XmlDocument xmldoc = new XmlDocument();
//加入一个根元素
XmlElement root = ("root");
//根元素添加命名空间属性
("xmlns:ns1", "/namespace1");
("xmlns:ns2", "/namespace2");
//添加子节点
XmlElement element1 = ("ns1:element1");
= "Value 1";
(element1);
//添加子节点
XmlElement element2 = ("ns2:element2");
= "Value 2";
(element2);
//添加子节点
XmlElement element3 = ("element3");
("xmlns", "/child");
= "Value 3";
(element3);
(root);
//保存创建好的XML文档
("");
();
("多个命名空间");
();
((""));
- 运行结果
多个命名空间
<root xmlns:ns1="/namespace1" xmlns:ns2="/namespace2">
<element1>Value 1</element1>
<element2>Value 2</element2>
<element3 xmlns="/child">Value 3</element3>
</root>
(5)XPath筛选节点数据
-
在C#中,可以使用XPath来筛选XML节点数据。XPath是一种用于在XML文档中查找信息的语言,它可以用来在XML文档中对元素和属性进行遍历。
-
XPath常见节点选择方法
-
//
:选择所有的节点,包括根节点。 -
.
:选择当前节点。 -
..
:选择当前节点的父节点。 -
/
:选择根节点下的所有节点。 -
//A
:选择所有名为"A"的节点。 -
//A/B
:选择所有名为"A"的节点的"B"子节点。 -
//A/*
:选择所有名为"A"的节点下的所有任意节点 -
//A[1]
:选择文档中第一个名为"A"的节点。 -
//A[@属性='属性值']
:选择所有名为"A"的节点,且属性=属性值的节点。 -
//A[contains(@属性, “属性值”)]
:选择所有名为"A"的节点,且属性包含属性值的节点。 -
//A[B='C']
:选择所有名为"A"的且子节点B等于’C’的节点。 -
//A[B!='C']
:选择所有名为"A"的且子节点B不等于’C’的节点。 -
//A[B!='C']
:选择所有名为"A"的且子节点B不等于’C’的节点。 -
//A[B>'C']
:选择所有名为"A"的且子节点B大于’C’的节点。 -
//A[B<'C']
:选择所有名为"A"的且子节点B小于’C’的节点。 -
//A[B>='C']
:选择所有名为"A"的且子节点B大于等于’C’的节点。 -
//A[B<='C']
:选择所有名为"A"的且子节点B小于等于’C’的节点。 -
//A[B<='C' and B>='D']
:选择所有名为"A"的且子节点B小于等于’C’且B大于等于’D’的节点。 -
//A[B<='C' or B>='D']
:选择所有名为"A"的且子节点B小于等于’C’或者B大于等于’D’的节点。 -
//*[@属性='属性值']
:选择所有属性=属性值的节点。 -
//A[@属性='属性值'][1]
:选择文档中第一个名为"A"的节点,且属性=属性值的节点。 -
//A[@属性='属性值']/B
:选择所有名为"A"的节点,且属性=属性值的节点的"B"子节点。
-
-
假设当前文件如下:
<root xmlns:companya="/companya" xmlns:companyb="/companyb">
<companya:customer1 type='ACCCCC'>
<name>John</name>
<age>10</age>
</companya:customer1>
<companya:customer1 type='BCCCCC'>
<name>Jane</name>
<age>15</age>
</companya:customer1>
<companya:customer2 type='CCCCCC'>
<name>Peter</name>
<age>20</age>
</companya:customer2>
<companya:customer3 type='DCCCCC'>
<name>Nancy</name>
<age>25</age>
</companya:customer3>
<companyb:customer1 type="ACCCCC">
<name>Bob</name>
<age>30</age>
</companyb:customer1>
<companyb:customer2 type="BCCCCC">
<name>Jobs</name>
<age>33</age>
</companyb:customer2>
<companyb:customer3 type="CCCCCC">
<name>Andy</name>
<age>38</age>
</companyb:customer3>
<companyb:customer3 type="DCCCCC">
<name>Lee</name>
<age>40</age>
</companyb:customer3>
</root>
- 使用xpath进行筛选
//创建xml文档
XmlDocument xmldoc = new XmlDocument();
("");
("选择节点");
XPathNodeIterator iterator1 = ().Select("//root/*");
while (())
{
XPathNavigator navigator = ;
();
}
("选择节点+条件");
XPathNodeIterator iterator2 = ().Select("//root/*[age>10 and age<30]");
while (())
{
XPathNavigator navigator = ;
();
}
("筛选包含命名空间前缀节点");
//筛选包含命名空间前缀节点,需要定义好命名空间,作为参数传入筛选器,否则筛选器无法识别命名空间
XmlNamespaceManager company = new XmlNamespaceManager();
("companya", "/companya");
("companyb", "/companyb");
XPathNodeIterator iterator3 = ().Select("//companya:customer1", company);
while (())
{
XPathNavigator navigator = ;
();
}
("筛选包含命名空间前缀节点+条件");
XPathNodeIterator iterator4 = ().Select("//companya:customer1[contains(name,'o')]", company);
while (())
{
XPathNavigator navigator = ;
();
}
- 运行结果如下:
选择节点
<companya:customer1 type="ACCCCC" xmlns:companya="/companya">
<name>John</name>
<age>10</age>
</companya:customer1>
<companya:customer1 type="BCCCCC" xmlns:companya="/companya">
<name>Jane</name>
<age>15</age>
</companya:customer1>
<companya:customer2 type="CCCCCC" xmlns:companya="/companya">
<name>Peter</name>
<age>20</age>
</companya:customer2>
<companya:customer3 type="DCCCCC" xmlns:companya="/companya">
<name>Nancy</name>
<age>25</age>
</companya:customer3>
<companyb:customer1 type="ACCCCC" xmlns:companyb="/companyb">
<name>Bob</name>
<age>30</age>
</companyb:customer1>
<companyb:customer2 type="BCCCCC" xmlns:companyb="/companyb">
<name>Jobs</name>
<age>33</age>
</companyb:customer2>
<companyb:customer3 type="CCCCCC" xmlns:companyb="/companyb">
<name>Andy</name>
<age>38</age>
</companyb:customer3>
<companyb:customer3 type="DCCCCC" xmlns:companyb="/companyb">
<name>Lee</name>
<age>40</age>
</companyb:customer3>
选择节点+条件
<companya:customer1 type="BCCCCC" xmlns:companya="/companya">
<name>Jane</name>
<age>15</age>
</companya:customer1>
<companya:customer2 type="CCCCCC" xmlns:companya="/companya">
<name>Peter</name>
<age>20</age>
</companya:customer2>
<companya:customer3 type="DCCCCC" xmlns:companya="/companya">
<name>Nancy</name>
<age>25</age>
</companya:customer3>
筛选包含命名空间前缀节点
<companya:customer1 type="ACCCCC" xmlns:companya="/companya">
<name>John</name>
<age>10</age>
</companya:customer1>
<companya:customer1 type="BCCCCC" xmlns:companya="/companya">
<name>Jane</name>
<age>15</age>
</companya:customer1>
筛选包含命名空间前缀节点+条件
<companya:customer1 type="ACCCCC" xmlns:companya="/companya">
<name>John</name>
<age>10</age>
</companya:customer1>
5、C#实现XML配置文件的读写
(1)创建一个XML配置文件
<Config>
<Item Key="Color">Red</Item>
</Config>
(2)实现读写帮助类
using ;
namespace MyXML
{
public class XmlConfigHelper
{
/// <summary>
/// 获取值
/// </summary>
/// <param name="xmlFilePath"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string GetValue(string xmlFilePath,string key)
{
XmlDocument xmlDoc = new XmlDocument();
(xmlFilePath);
XmlNode valueNode = ($"/Config/Item[@Key='{key}']");
if (valueNode != null)
{
return ;
}
return null;
}
/// <summary>
/// 设置值,没有新增
/// </summary>
/// <param name="xmlFilePath"></param>
/// <param name="key"></param>
/// <param name="value"></param>
public static void SetValue(string xmlFilePath, string key, string value)
{
XmlDocument xmlDoc = new XmlDocument();
(xmlFilePath);
XmlNode valueNode = ($"/Config/Item[@Key='{key}']");
if (valueNode != null)
{
= value;
}
else
{
XmlElement newElement = ("Item");
("Key", key);
= value;
("/Config").AppendChild(newElement);
}
(xmlFilePath);
}
/// <summary>
/// 判断是否有key
/// </summary>
/// <param name="xmlFilePath"></param>
/// <param name="key"></param>
/// <returns></returns>
public static bool HasKey(string xmlFilePath, string key)
{
XmlDocument xmlDoc = new XmlDocument();
(xmlFilePath);
XmlNode valueNode = ($"/Config/Item[@Key='{key}']");
return valueNode != null;
}
/// <summary>
/// 删除key
/// </summary>
/// <param name="xmlFilePath"></param>
/// <param name="key"></param>
public static void DeleteKey(string xmlFilePath, string key)
{
XmlDocument xmlDoc = new XmlDocument();
(xmlFilePath);
XmlNode valueNode = ($"/Config/Item[@Key='{key}']");
if (valueNode != null)
{
("/Config").RemoveChild(valueNode);
}
(xmlFilePath);
}
}
}
(3)调用帮助类读写配置
("读取配置");
($"Color:{("", "Color")}");//Red
("设置配置");
("", "Color","Green");
($"Color:{("", "Color")}");//Green
("", "Color", "Red");
("添加配置");
($"Has NewColor:{("", "NewColor")}");//False
("", "NewColor", "Green");
($"NewColor:{("", "NewColor")}");//Green
("删除配置");
($"Has NewColor:{("", "NewColor")}");//True
("", "NewColor");
($"Has NewColor:{("", "NewColor")}");//False