C#中的Linq to Xml详解
2021-06-14 19:03
标签:示例 += render pac setvalue images type 优点 ext 这篇文章主要介绍了C#中的Linq to Xml详解,本文给出转换步骤以及大量实例,讲解了生成xml、查询并修改xml、监听xml事件、处理xml流等内容,需要的朋友可以参考下 操作之前,需要引入 程序集和命名空间 一、生成Xml 为了能够在结构有一定的组织,笔者建议大家新建一个控制台项目,并且新建一个CreateXml类(以下部分都属于该类中)。 并在其中写入以下属性: 这句代码很好理解,就是为了下面我们示例的时候可以将xml保存到当前程序的运行路径下。 (以下的示例中不会包含Main方法中的写法,因为Main中仅仅只要调用该静态方法即可。) 1.创建简单的Xml 首先我们先练练手,创建一个简单的Xml并保存到一个文件中。 很多学习过XML的人可以从结构就能够猜测出最终的xml的组织,而这也是linq to xml的优点之一。这句代码首先创建一个xml文档,并设置该xml的版本为1.0, 采用utf-8编码,后面的yes表示该xml是独立的。下面就开始创建每个节点的,首先是Root节点,然后在Root节点中添加两个Item节点。 最终生成的Xml如下所示: 2.创建注释 当xml有很多项时,我们就需要利用注释加以区别,通过linq to xml我们一样可以在其中添加注释。 代码如下: 这里我们直接在版本信息的后面添加了一条注释。 最终的结果如下所示: 3.根据对象创建xml 很多时候我们都会将数组之类的类型转换成xml以便保存进永久性存储介质中,所以下面我们也简单的举了一个例子,将数组转换成xml。 代码如下所示: 一开始的代码 var s = Enumerable.Radge(1,10)是从1开始递增,生成含有10项的数组,以便后面我们进行添加,有了这个数组之后, 我们通过简单的linq语句将数组转换成xml,添加到Root中。 保存之后的结果如下: 代码如下: 4.创建属性 有时我们不想创建新的子项去保存数据,而是使用属性的方式去保存。理所应当,linq to xml一样也支持这个功能,下面我们可以通过简单的语句去实现它。 代码如下所示: 我们依然可以看到熟悉的语法,这里我们利用了XAttribute去创建一个属性,并添加到XElement中。 最终的结果如下: 5.创建命名空间 对于一些企业级的xml格式,会非常的严格。特别是在同一个xml中可能会出现重复的项,但是我们又想区分开来,这个时候我们可以利用命名空间将他们分开(跟C#中的命名空间类似。)。 下面是创建命名空间的示例: 结果如下所示: 从这个结果中我们可以看到对应的属性中有了xmlns属性,并且值就是我们赋给它的命名空间。 二、查询并修改Xml Linq to xml不仅仅是创建xml简单,在查询,编辑和删除方面一样是非常方便的。下面我们就会介绍这些。 首先我们创建一个QueryXml类,并在其中写入如下的属性: 同时在该路径下新建一个test1.xml文件,并在其中写入如下内容: 1.通过文件读取xml 既然我们要对xml查询就需要读取对应的xml文件,当然后面会介绍其他的方式。 代码如下: 我们可以利用XElement的静态方法Load读取指定路径下的xml文件,这里我们不仅读取了该xml文件,同时还获取的该xml的第一个item的值并输出。 所以我们可以看到如下的结果:
2.在指定节点前后添加新节点 上面我们仅仅只是读取xml以及简单的查询,下面我们不仅仅查询并且还要在该节点前后插入新的节点。 代码如下: 我们简单的分析一下上面的代码,首先我们利用linq从中查询Item的值为Item2的节点,然后获取其中第一个节点,然后通过AddAfterSelf和AddBeforeSelf在该节点的后面和前面分别添加新的节点。 添加完之后的xml结果如下: 3.添加属性到节点中 我们已经可以动态的添加节点,但是创建的时候不仅仅可以创建节点,并且还能创建属性,下面我们可以通过SetAttributeValue去添加新的属性或者修改现有属性。 代码如下: 我们可以明显的看出,这里我们已经不是使用XElement.Load去读取xml文件,而是通过直接读取xml字符串。接着我们还是跟上面一样去查询,然后通过SetAttributeValue添加了新的属性,并保存。 Xml内容如下: 我们可以看到第二个Item中多了一个 v3=”3” 新的属性。 4.添加注释到指定节点前后 这里的语法基本跟添加节点到指定节点前后是相似的,只是读取xml的方式不同。 代码如下: 上面我使用StringReader和TextReader读取xml字符串并使用XElement.Load读取该对象,然后就是在新建节点的时候新建的是注释节点,最后利用一样的语法添加到指定节点前后。 最终结果如下: 5.替换指定节点 修改节点的值通过SetValue即可做到,但是有时涉及到子节点,而我们想一次性全部替换掉,那么我们就需要使用ReplaceWith。 代码如下: 这里的重点在于ReplaceWith方法,调用该方法会发生两个操作。首先是删除该节点,然后在该节点的位置上将我们的节点插入完成替换。 最后的xml结果如下: 这样我们很轻易的就替换了整个节点。 6.删除指定属性 前面我们介绍了创建、修改和添加属性,但是还没有介绍如何删除指定的属性,下面我们就通过一个简单的实例来演示。 代码如下: 我们首先查询出指定的节点,然后指定某个属性,最后调用XAttribute的Remove方法既可。 结果如下: 7.删除指定节点 既然上面已经可以删除属性,自然也少不了删除属性。 代码如下所示: 结果如下: 三、按节点关系查询 上面的查询都是通过相关的条件进行查询,但是我们有时仅仅只需要通过之间的关系即可,这样反而可以避免很多的代码,当然稍加探索可以发现其实XElement都提供给我们了。 我们依然要新建一个StructureXml类,并在其中新建一个属性。 如下所示: 同时在该文件夹下新建一个test2.xml并写入如下内容: 1.显示指定节点的所有父节点 通过上面的xml文件,我们清晰的看出xml是具有结构性的,彼此之间都存在关系,而现在我们需要显示某个节点的父级节点的名称。 代码如下所示: 其中我们通过Descendants获取最底的节点,然后使用Ancestors获取所有的父级节点,而AncestorsAndSelf则表示包含本身。 最终结果如下所示:
我们从图中看出,分割线前显示的是不包含本身的,而下面是包含本身的。 2.显示指定节点的所有子节点 我们不仅仅可以输出一个节点的所有父级节点,同样也可以输出一个节点的所有子节点。 代码如下所示: 这里我们依然是分成输出子级节点以及包含自己的。 结果如下所示:
3.显示同级节点之前的节点 既然有了父子关系,当然也少不了同级关系,首先我们先显示同级节点之前的节点。 代码如下所示: 这里我们看到我们通过ElementsBeforeSelf获取该节点之前的同级节点,当然我们还可以传入参数作为限制条件。这里我们通过查询获取了SubItem这个节点,并显示该节点之前的同级节点。 最终结果如下:
4.显示同级节点后面的节点 作为上面的补充。 代码如下所示 最终结果如下所示:
四、监听xml事件 你可能会疑惑xml为什么还要监听,其实这样是有意义的,比如你要根据某个节点的值作为依赖,那么你就要监听这个节点,如果这个节点发生改变的时候, 你才可以及时的作出反应。但是xml的事件监听有一个特点,跟浏览器中的DOM事件类似,监听父节点同样也可以监听的到它的子节点的事件。下面我们 通过一个简单的实例来说明。 实例代码如下: 最终结果如下所示:
五、处理xml流 在实际的商业化的开发中,xml不可能仅仅保存这么点数据。有可能保存着非常多的数据。但是我们还是按照以往的方式,就会将xml全部读取进内存。 这样会占据很多内存,影响系统的性能,针对这种情况我们需要使用流的方式去处理xml,因为流会按照我们的顺序读取部分xml进内存,并不会将所 有xml都读取进内存。 Xml文件内容如下所示: 代码如下所示: 这里我们通过XmlReader的Create静态方法打开xml文件,并通过Read一个节点的进行读取,并判断该节点的类型。 最终结果如下: C#中的Linq to Xml详解 标签:示例 += render pac setvalue images type 优点 ext 原文地址:https://www.cnblogs.com/net-sky/p/10412082.html System.Xml.Linq;
public static String Path
{
get
{
String path = String.Format("{0}\\test.xml", Environment.CurrentDirectory);
return path;
}
}
///
///
///
///
///
public static String Path
{
get
{
String path = String.Format("{0}\\test1.xml", Environment.CurrentDirectory);
return path;
}
}
下面我们就可以正式开始了。///
///
///
///
///
///
///
依然是调用同样的方法。public static String Path
{
get
{
String path = String.Format("{0}\\test2.xml", Environment.CurrentDirectory);
return path;
}
}
///
///
///
///
public static class EventXml
{
public static void BindChangeing()
{
XElement xele = new XElement("Root");
xele.Changing += xele_Changing;
xele.Changed += xele_Changed;
xele.Add(new XElement("Item", "123"));
var item = xele.Element("Item");
item.ReplaceWith(new XElement("Item", "2"));
item = xele.Element("Item");
item.Remove();
Console.ReadKey();
}
static void xele_Changed(object sender, XObjectChangeEventArgs e)
{
XElement ele = sender as XElement;
Console.WriteLine(String.Format("已完成 {0}-{1}", ele.Name, e.ObjectChange));
}
static void xele_Changing(object sender, XObjectChangeEventArgs e)
{
XElement ele = sender as XElement;
Console.WriteLine(String.Format("正在进行中 {0}-{1}", ele.Name, e.ObjectChange));
}
}
其中的关键就是Changing和Changed事件,其次就是在事件中判断事件的来源。public static class ReadXmlStream
{
public static String Path
{
get
{
String path = String.Format("{0}\\test3.xml", Environment.CurrentDirectory);
return path;
}
}
///