一、XML基本概述
XML文件是一种常用的文件格式,例如WinForm里面的app.config以及Web程序中的web.config文件,还有许多重要的场所都有它的身影。Xml是Internet环境中跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有力工具。XML是一种简单的数据存储语言,使用一系列简单的标记描述数据,而这些标记可以用方便的方式建立,虽然XML占用的空间比二进制数据要占用更多的空间,但XML极其简单易于掌握和使用。微软也提供了一系列类库来倒帮助我们在应用程序中存储XML文件。
“在程序中访问进而操作XML文件一般有两种模型,分别是使用DOM(文档对象模型)和流模型,使用DOM的好处在于它允许编辑和更新XML文档,可以随机访问文档中的数据,可以使用XPath查询,但是,DOM的缺点在于它需要一次性的加载整个文档到内存中,对于大型的文档,这会造成资源问题。流模型很好的解决了这个问题,因为它对XML文件的访问采用的是流的概念,也就是说,任何时候在内存中只有当前节点,但它也有它的不足,它是只读的,仅向前的,不能在文档中执行向后导航操作。
三种常用的读取XML文件的方法。分别是
①使用XmlDocument
②使用XmlTextReader
③使用Linq to Xml
本文主要讨论使用Linq to Xml的方法实现对XML文档的创建、增加、删除、修改、查询的操作。
二、创建XML文档
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace CreateXML
{
class Program
{
static void Main(string[] args)
{
//实例化XDocument对象
XDocument xdoc = new XDocument();
//创建根节点
XElement root = new XElement("school");
//创建子节点
XElement cls = new XElement("class");
cls.SetAttributeValue("number", "0302"); //添加子节点的属性,如3年级2班
//创建子节点class的子节点学生stu1
XElement stu1 = new XElement("student");
stu1.SetAttributeValue("id", "001"); //添加子节点stu1的属性,如学号001
stu1.SetElementValue("name", "张三"); //添加子节点stu1的数据,如姓名张三
stu1.SetElementValue("gender", "男"); //添加子节点stu1的数据,如性别男
stu1.SetElementValue("age", "19"); //添加子节点stu1的数据,如年龄19
//创建子节点class的子节点学生stu2
XElement stu2 = new XElement("student");
stu2.SetAttributeValue("id", "002"); //添加子节点stu2的属性,如学号002
stu2.SetElementValue("name", "李晓梅"); //添加子节点stu2的数据,如姓名李晓梅
stu2.SetElementValue("gender", "女"); //添加子节点stu2的数据,如性别女
stu2.SetElementValue("age", "18"); //添加子节点stu2的数据,如年龄18
cls.Add(stu1); //添加student到class
cls.Add(stu2); //添加student到class
root.Add(cls); //添加子节点class到根节点school
xdoc.Add(root); //添加根节点到XDoucment对象
xdoc.Save("1.xml"); //使用XML的保存会自动在xml文件开始添加:
Console.WriteLine("创建XML文件成功!");
Console.ReadKey();
}
}
}
生成的xml文档如下:
<school>
<class number="0302">
<student id="001">
<name>张三name>
<gender>男gender>
<age>19age>
student>
<student id="002">
<name>李晓梅name>
<gender>女gender>
<age>18age>
student>
class>
school>
三、读取XML文档
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace ReadXML
{
class Program
{
static void Main(string[] args)
{
string path = "1.xml";
XDocument xdoc = XDocument.Load(path); //加载xml文件
XElement rootSchool = xdoc.Root; //获取根元素
//Console.WriteLine(rootSchool.Name); //根元素的名字
IEnumerable<XElement> xeles = rootSchool.Elements(); //获取根元素下所有的直接子元素
foreach (XElement xeleClass in xeles)
{
foreach (XElement xeleStudent in xeleClass.Elements())
{
Console.WriteLine(xeleStudent.Name); //获取节点名
Console.WriteLine(xeleStudent.Attribute("id").Value); //获取属性值
Console.WriteLine(xeleStudent.Element("name").Value); //下面3行是获取数据
Console.WriteLine(xeleStudent.Element("gender").Value);
Console.WriteLine(xeleStudent.Element("age").Value);
}
}
Console.ReadKey();
}
}
}
运行结果如下图:
三、增加XML文档内容
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace AddXML
{
class Program
{
static void Main(string[] args)
{
string path = "1.xml";
XDocument xdoc = XDocument.Load(path);
XElement xeleRoot = xdoc.Root;
//在已存在的节点上添加属性和数据
XElement xeleClass = xeleRoot.Element("class");
XElement xeleStu3 = new XElement("student");
xeleStu3.SetAttributeValue("id", "005");
xeleStu3.SetElementValue("name", "王五");
xeleStu3.SetElementValue("gender", "男");
xeleStu3.SetElementValue("age", "40");
xeleClass.Add(xeleStu3);
//在根节点下添加新的直接子节点及次级节点的属性和数据
//XElement xeleClass = new XElement("class");
//xeleClass.SetAttributeValue("number", "0501");
//XElement xeleStu1 = new XElement("student");
//xeleStu1.SetAttributeValue("id", "003");
//xeleStu1.SetElementValue("name","刘芳");
//xeleStu1.SetElementValue("gender","女");
//xeleStu1.SetElementValue("age","26");
//XElement xeleStu2 = new XElement("student");
//xeleStu2.SetAttributeValue("id", "004");
//xeleStu2.SetElementValue("name", "王亮");
//xeleStu2.SetElementValue("gender", "男");
//xeleStu2.SetElementValue("age", "36");
//xeleClass.Add(xeleStu1);
//xeleClass.Add(xeleStu2);
//xeleRoot.Add(xeleClass);
xdoc.Save("1.xml");
Console.WriteLine("添加xml成功");
Console.ReadKey();
}
}
}
在已存在的节点上添加属性和数据,xml文件如下:
<school>
<class number="0302">
<student id="001">
<name>张三name>
<gender>男gender>
<age>19age>
student>
<student id="002">
<name>李晓梅name>
<gender>女gender>
<age>18age>
student>
<student id="005">
<name>王五name>
<gender>男gender>
<age>40age>
student>
class>
school>
上面被消隐的代码放开之后,在根节点下添加新的直接子节点及次级节点的属性和数据 ,xml文件如下:
<school>
<class number="0302">
<student id="001">
<name>张三name>
<gender>男gender>
<age>19age>
student>
<student id="002">
<name>李晓梅name>
<gender>女gender>
<age>18age>
student>
class>
<class number="0501">
<student id="003">
<name>刘芳name>
<gender>女gender>
<age>26age>
student>
<student id="004">
<name>王亮name>
<gender>男gender>
<age>36age>
student>
class>
school>
四、删除XML文档内容
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace DeleteXML
{
class Program
{
static void Main(string[] args)
{
XDocument xdoc = XDocument.Load("1.xml");
XElement xeleRoot = xdoc.Root;
//删除根节点的直接子节点
XElement xeleClass = xeleRoot.Elements("class").Where(x => x.Attribute("number").Value == "0302").Single(); //拉姆达表达式
xeleClass.Remove();
//删除根节点的直接子节点的下一级节点
//XElement xeleClass = xeleRoot.Elements("class").Where(x => x.Attribute("number").Value == "0302").Single(); //获取班级号为0302的直接子节点
//XElement xeleStudent = xeleClass.Elements("student").Where(x => x.Attribute("id").Value == "001").Single(); //获取学号为001的直接子节点的下一级节点
//xeleStudent.Remove();
xdoc.Save("1.xml");
Console.WriteLine("删除节点成功!");
Console.ReadKey();
}
}
}
删除根节点的直接子节点,xml文件如下:
<school>
<class number="0501">
<student id="003">
<name>刘芳name>
<gender>女gender>
<age>26age>
student>
<student id="004">
<name>王亮name>
<gender>男gender>
<age>36age>
student>
class>
school>
删除根节点的直接子节点的下一级节点,xml文件如下:
<school>
<class number="0302">
<student id="002">
<name>李晓梅name>
<gender>女gender>
<age>18age>
student>
class>
<class number="0501">
<student id="003">
<name>刘芳name>
<gender>女gender>
<age>26age>
student>
<student id="004">
<name>王亮name>
<gender>男gender>
<age>36age>
student>
class>
school>
五、修改XML文档内容
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace UpdateXML
{
class Program
{
static void Main(string[] args)
{
XDocument xdoc = XDocument.Load("1.xml");
XElement xeleRoot = xdoc.Root;
XElement xeleClass = xeleRoot.Elements("class").Where(x => x.Attribute("number").Value == "0302").Single(); //获取班级号为0302的直接子节点
XElement xeleStudent = xeleClass.Elements("student").Where(x => x.Attribute("id").Value == "001").Single(); //获取学号为001的直接子节点的下一级节点
xeleStudent.SetAttributeValue("id", "008");
xeleStudent.SetElementValue("name","邦德");
xeleStudent.SetElementValue("gender","爷们");
xeleStudent.SetElementValue("age","39");
xdoc.Save("1.xml");
Console.WriteLine("修改成功!");
Console.ReadKey();
}
}
}
执行后xml文件如下:
<school>
<class number="0302">
<student id="008">
<name>邦德name>
<gender>爷们gender>
<age>39age>
student>
<student id="002">
<name>李晓梅name>
<gender>女gender>
<age>18age>
student>
class>
<class number="0501">
<student id="003">
<name>刘芳name>
<gender>女gender>
<age>26age>
student>
<student id="004">
<name>王亮name>
<gender>男gender>
<age>36age>
student>
class>
school>
这种方式会首先将xml 全load下来,对于大的xml 使用XmlReader 更合适
https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmlreader?view=net-5.0