C#中的Linq To XML讲解
作者:springsnow 发布时间:2021-06-29 18:39:43
一、概述
Overview - LINQ to XML | Microsoft 官方文档
LINQ to XMLLINQ to XML 是一种启用了 LINQ 的内存 XML 编程接口,使用它,可以在 .NET Framework.NET Framework 编程语言中处理 XML。
在使用LINQ to XML时需要添加System.Xml.Linq.dll的引用。
XElement类 表示XML元素,它是XContainer类的派生类,而XContainer类又派生于XNode类。一个元素就是一个节点。
XElement是LINQ to XML最重要最基本的类之一,它包含所有创建和操作XML元素所必需的功能。通过它可以创建元素,添加和修改元素的属性,操作元素的内容等。XAttribute类 用来处理属性,属性是与元素相关联的名称/值对。
XDocument类 提供了处理有效XML文档的方法,包括声明、注释和处理指令。XDocument类派生自XContainer类,可以有子节点。XML标准限值XDocument对象只包含单个XElement子节点,此节点作为根节点或跟元素。
继承关系:
XNode(抽象)类派生类有:XText、XComment、XDocumentType、XProcessingInstruction、XContainer
XContainer(抽象)类派生类有:XElement、XDocument.
二、加载XML文件
1、从文件中输入XML数据
//1、从URI中获取XML数据,支持本地路径和URL,支持对应枚举的设置
XElement xe1 = XElement.Load(@"D:\123.xml",LoadOptions.None);
//2、从XmlReader中加载
XmlReader xr = XmlReader.Create(@"D:\123.xml");
XElement xe2 = XElement.Load(xr);
//3、从TextReader中获取数据
TextReader reader = File.OpenText(@"D:\123.xml");
XElement xe3 = XElement.Load(reader);
//4、从Stream中读取
XElement xe4 = XElement.Load(new FileStream(@"D:\123.xml", FileMode.Open, FileAccess.Read));
2、从字符串中输入XML数据
string xmlString = "刘备28";
XElement xe = XElement.Parse(xmlString, LoadOptions.SetLineInfo);
三、生成XML元素或XML文档
1、创建XML元素
XElement xml =
new XElement("Persons",
new XElement("Person",
new XElement("Name", "刘备"),
new XElement("Age", "28")
),
new XElement("Person",
new XElement("Name", "关羽"),
new XElement("Age", "27")
)
);
xml.Save(@"D:\123.xml");
2、创建XML文档
//创建处理指令
XProcessingInstruction instruction = new XProcessingInstruction("xml-stylesheet","href=\"hello.css\" type = \"text/css\"");
//创建声明对象
XDeclaration xDeclaration = new XDeclaration("1.0","GB2312","yes");
//创建文档类型
XDocumentType documentType = new XDocumentType("Person", null, "Person.dtd", null);
//创建XmlCData数据
XCData data = new XCData("神奇的刘备");
//创建XDocument文档
XDocument xDoc = new XDocument();
XElement xml =
new XElement("Persons",
new XElement("Person",
new XAttribute("Description", "此人龙凤之姿 天日之表;"),
new XElement("Name", data),
new XElement("Age", "28")
),
new XElement("Person",
new XElement("Name", "关羽"),
new XElement("Age", "27")
)
);
xDoc.Add(documentType);
xDoc.Add(instruction);
xDoc.Declaration = xDeclaration;
xDoc.Add(xml);
xDoc.Save(@"D:\123.xml");
3、Linq查询生成XML
我们实例化一个book的集合
Book[] books = new Book[] {
new Book("Ajax in Action", "Manning", 2005),
new Book("Windows Forms in Action", "Manning", 2006),
new Book("RSS and Atom in Action", "Manning", 2006)
};
如果我们现在想将Year== 2006的集合创建成以下XML格式
<books>
<book title="Windows Forms in Action">
<publisher>Manning</publisher>
</book>
<book title="RSS and Atom in Action">
<publisher>Manning</publisher>
</book>
</books>
采用linq方式
XElement xml = new XElement("books",
from book in books
where book.Year == 2006
select new XElement("book",
new XAttribute("title", book.Title),
new XElement("publisher", book.Publisher)
)
);
// 显示这个XML
Console.WriteLine(xml);
传统方式
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("books");
foreach (Book book in books)
{
if (book.Year == 2006)
{
XmlElement element = doc.CreateElement("book");
element.SetAttribute("title", book.Title);
XmlElement publisher = doc.CreateElement("publisher");
publisher.InnerText = book.Publisher;
element.AppendChild(publisher);
root.AppendChild(element);
}
}
doc.AppendChild(root);
// 显示这个XML
doc.Save(Console.Out);
4、属性转出元素
XML文件:
<?xml version="1.0" encoding="utf-8" ?>
<Root Data1="123" Data2="456">
<Child1>Content</Child1>
</Root>
您可以编写一些过程代码以便从属性创建元素,然后删除属性
linq方式:
XElement root = XElement.Load("Data.xml");
XElement newTree = new XElement("Root",
root.Element("Child1"),
from att in root.Attributes()
select new XElement(att.Name, (string)att)
);
xml.Save(@"D:\123.xml");
传统方式:
XElement root = XElement.Load("Data.xml");
foreach (XAttribute att in root.Attributes()) {
root.Add(new XElement(att.Name, (string)att));
}
root.Attributes().Remove();
5、XmlDocument转换为XDocument
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlStr); //xml字符串转成xml文档对象
XDocument xdoc = doc.ToXDocument(); //xmldocument转成xdoccument 扩展方法
var eventId = xdoc.Document.Root.Element("EventID"); //根节点下的eventid节点
if (eventId != null)
{
MessageBox.Show(eventId.Value); //15
}
扩展方法
public static class XmlDocumentExtensions
{
public static XDocument ToXDocument(this XmlDocument document)
{
return document.ToXDocument(LoadOptions.None);
}
public static XDocument ToXDocument(this XmlDocument document, LoadOptions options)
{
using (XmlNodeReader reader = new XmlNodeReader(document))
{
return XDocument.Load(reader, options);
}
}
}
四、XML数据的输出
XElement有个Save,这个Save有多种重载,支持将XML数据输入到各处(文件地址,流,TextWriter,XmlWriter)。
XElement xml =
new XElement("Persons",
new XElement("Person",
new XElement("Name", "刘备"),
new XElement("Age", "28")
)
);
//1、输出到文件
xml.Save(@"D:\123.xml");
//2、输出到TextWriter
TextWriter tw = new StringWriter();
//第二个参数SaveOptions枚举支持设置格式,缩进,保留无关重要的空白,去除重复命名空间
xml.Save(tw, SaveOptions.None);
Console.WriteLine(tw);
//3、输出到Stream
using (MemoryStream mem = new MemoryStream())
{
xml.Save(mem);
Console.WriteLine(Encoding.UTF8.GetString(mem.ToArray()));
}
//4、输出到XmlWriter
XmlWriter xw = XmlWriter.Create(@"D:\LinqToXml.xml");
xml.Save(xw);
xw.Flush();
五、查询
Element() :获取当前XML元素的第一个具有指定名称的子元素
Elements() :获取当前XML元素的所有子元素,或具有指定名称的所有子元素,返回类型为IEnumerable的可用LINQ进行查询的元素集合
Attribute(): 获取当前XML元素的具有指定名称的属性
Attributes(): 获取当前XML元素的所有属性或者具有指定名称的属性, 返回类型为IEnumerable的LINQ集合
1、查询根元素
IEnumerable elements = from e in doc.Elements("Products")
select e;
foreach (XElement e in elements)
{
Console.WriteLine("{0}-{1}", e.Name, e.Value);
}
2、查询节点
var query = from p in doc.Element("Products").Elements("Product")
where (int)p.Element("ProductID") == 1
orderby p.Attribute("ID").Value
select p;
query.ToList().ForEach(item =>
{
Console.WriteLine("{0}-{1}-{2}", item.Element("ProductID").Value, item.Element("ProductName").Value, item.Element("UnitPrice").Value);
});
3、查询子孙节点
Descendants轴方法与Elements类型相似,不过Elements只查找当前元素下的直接子节点,而Descendants则会遍历当前元素下任意层级的子元素。
var query = from b in root.Descendants("Book")
select b;
foreach (var item in query)
{
Console.WriteLine(item.Element("ProductName").Value);
}
4、查询属性
var query = from p in xml.Nodes().OfType()
where (int)p.Attribute("ID").Value == 1
select new
{
ID = p.Attribute("ID").Value,
ProductID = p.Element("ProductID").Value,
ProductName = p.Element("ProductName").Value
};
5、查询出来填充到List:
XElement root = XElement.Load(@"like.xml");
var query =
from ele in root.Elements("book")
select new { author = ele.Element("author").Value,
price = ele.Element("price").Value
};
String xml = null;
foreach (var item in query)
{
xml = xml + item.ToString() + "\n ------- \n";
}
六、操作节点
1、增加节点
Add(): 在 XContainer 的子内容的末尾添加内容。
AddFirst(): 在 XContainer 的子内容的开头添加内容。
AddAfterSelf(): 在 XNode 后面添加内容。
AddBeforeSelf() : 在 XNode 前面添加内容。
XElement product = new XElement
(
"Product",
new XAttribute("ID", 2),
new XElement("ProductName", "LINQ to Object"),
new XElement("UnitPrice", 20m),
new XElement("Remark", "")
);
el.Add(product);
2、修改、替换节点
SetAttributeValue(): 设置属性的值。 如果该属性不存在,则创建该属性。 如果值设置为 null,则移除该属性。
SetElementValue(): 设置子元素的值。 如果该元素不存在,则创建该元素。 如果值设置为 null,则移除该元素。
Value:用指定的文本替换元素的内容(子节点)。
SetValue(): 设置元素的值。
ReplaceAll (): 替换元素的所有内容(子节点和属性)。
ReplaceAttributes(): 替换元素的属性。
ReplaceWith(): 用新内容替换节点。
ReplaceNodes(): 用新内容替换子节点。
IEnumerable products = from e in el.Elements("Product")
where e.Attribute("ID").Value == "1"
select e;
if (products.Count() > 0)
{
XElement product = products.First();
product.SetAttributeValue("ID", 3);
product.ReplaceNodes
(
new XElement("ProductName", "LINQ to XML Version 2"),
new XElement("UnitPrice", 30)
);
}
3、删除节点
RemoveAll(): 移除元素的所有内容(子节点和属性)。
RemoveAttributes(): 移除元素的属性。
ReplaceNodes(): 删除子节点。
Remove(): 移除掉整个节点或节点集合
IEnumerable products = from e in el.Elements("Product")
where e.Attribute("ID").Value == "2"
select e;
if (products.Count() > 0)
{
products.First().Remove();
}
xml.Element("Product").Remove(); // 删除第一个Product子元素
xml.Elements("Product").Remove(); // 删除全部Product子元素
xml.SetElementValue("Product", null); // 删除第一个Product子元素
xml.Element("Product").SetElementValue("ProductID", 1); // 修改ProductID子元素
xml.Element("Product").SetElementValue("ProductID", null); // 删除ProductID子元素
4、属性操作
//添加属性:
product.Add(new XAttribute("ID", 1));
//修改属性:
product.SetAttributeValue("ID", 2);
//删除属性:
product.Attribute("ID").Remove();
六、使用XPath查询
为了在LINQ XML中使用XPath查询,需要添加System.Xml.XPath命名空间。如下:
using Sytem.Xml.XPath;
添加了System.Xml.XPath命名空间,XNode类就添加了一系列扩展方法。有了这些扩展方法,我们可以有两种选择处理XML。使我们的应用程序可以进行一个平稳的移植。
CreateNavigator方法,这允许我们从一个现有的XNode对象创建一个XPathNavigator对象。
XPathEvaluate方法允许对XNode上的XPath表达式进行计算。
XPathSelectElement方法返回第一个匹配表达式的元素, XPathSelectElements方法返回所有匹配表达式的元素。
为了查询如下XML数据:
<category name="Technical">
<category name=".NET">
<books>
<book>CLR via C#</book>
<book>Essential .NET</book>
</books>
</category>
<category name="Design">
<books>
<book>Refactoring</book>
<book>Domain Driven Design</book>
<book>Patterns of Enterprise Application Architecture</book>
</books>
</category>
<books>
<book>Extreme Programming Explained</book>
<book>Pragmatic Unit Testing with C#</book>
<book>Head First Design Patterns</book>
</books>
</category>
如何使用XPath查询XML数据:
XElement root = XElement.Load("categorizedBooks.xml");
var books = from book in root.XPathSelectElements("//book")
select book;
foreach (XElement book in books)
{
Console.WriteLine((string)book);
}
七、XML进行转换
1、使用XSLT进行转换
string xsl =@"http://www.w3.org/1999/XSL/Transform'>Book Catalog by , ";
XElement books = XElement.Load("books.xml");
XDocument output = new XDocument();
using (XmlWriter writer = output.CreateWriter())
{
XslCompiledTransform xslTransformer = new XslCompiledTransform();
xslTransformer.Load(XmlReader.Create(new StringReader(xsl)));
xslTransformer.Transform(books.CreateReader(), writer);
}
Console.WriteLine(output);
为了重用转换代码,可以将转换逻辑封装到一个扩展方法中
public static class XmlExtensions
{
public static XDocument XslTransform(this XNode node, string xsl)
{
XDocument output = new XDocument();
using (XmlWriter writer = output.CreateWriter())
{
XslCompiledTransform xslTransformer = new XslCompiledTransform();
xslTransformer.Load(XmlReader.Create(new StringReader(xsl)));
xslTransformer.Transform(node.CreateReader(), writer);
}
return output;
}
}
//使用这个扩展方法
XElement.Load("books.xml").XslTransform(xsl));
2、使用 LINQ to XML 转换 XML
XSL 并不是改变 XML 格式的唯一方式(过去它是唯一实际可行的办法),但今天,LINQ to XML 提供了一个富有竞争力的选择。要使用 LINQ to XML 进行转换,你需要一个运用投影的 LINQ 表达式。技巧在于投影必须返回一个 XElement 而不是匿名类型。
string xmlFile = Server.MapPath("DvdList.xml");
XDocument doc = XDocument.Load(xmlFile);
XDocument newDoc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("Movies",
from DVD in doc.Descendants("DVD")
where (int)DVD.Attribute("ID") < 3
select new XElement[]
{
new XElement ("Moive",
new XAttribute("name", (string)DVD.Element("Title")),
DVD.Descendants("Star")
)
}
)
);
string newFile = Server.MapPath("MovieList.xml");
newDoc.Save(newFile);
结果:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Movies>
<Moive name="The Matrix">
<Star>Keanu Reeves</Star>
<Star>Laurence Fishburne</Star>
</Moive>
<Moive name="Forrest Gump">
<Star>Tom Hanks</Star>
<Star>Robin Wright</Star>
</Moive>
</Movies>
基于 LINQ 转换的语法通常要比使用 XSL 样式表的转换更容易理解,并且更加精确。你也可以很方便的替换为另一个 IEnumable的集合,包括 LINQ to Entities 获得的结果集,然后随意打包成另一种格式的 XML 文档。
来源:https://www.cnblogs.com/springsnow/p/9428755.html


猜你喜欢
- md5 属于hash算法一类,是不可逆的消息摘要算法。与对称加密和非对称加密算法不一样,不需要加密密钥。注意:md5不是加密算法,只是将数据
- 前言在上一篇,我们谈到了jvm垃圾回收算法详细解析,并了解了JVM中针对堆区中不同的分代采用不同的垃圾回收算法在了解了垃圾回收算法之后,很多
- 本文实例为大家分享了java模拟进度计量器的具体代码,供大家参考,具体内容如下一、程序说明1、自定义模拟血压计外观图class M
- 在许多游戏中当我们因为一些问题无法接着进行游玩,我们都会选择保存,以便后面有空时,接着游玩。接下来,我们会学习一些Unity有关的存储方法。
- 1、启动新Activty1.1、功能分析App功能在第一个Activity输入消息点击第一个Activity的发送按钮发送消息到第二个Act
- 概述源码就是能够被用来执行,生成机器能够识别的代码,通过开源源码,可以引用其功能。重要性1、mybatis中的sql执行,不仅要知道返回的结
- 此方案适用于解决springboot项目运行时动态添加数据源,非静态切换多数据源!!!一、多数据源应用场景:1.配置文件配置多数据源,如默认
- 之前有学弟问过我一道java的面试题,题目不算难。用java实现杨辉三角。我花了点时间整理了一下,发现挺有意思的,于是想写下来分享一下。在写
- 本文实例为大家分享了C# Winform 自动更新程序,供大家参考,具体内容如下第一步:检查更新检查更新其实无非就是去比较更新包的版本和本地
- Java 中HttpURLConnection附件上传的实例详解整合了一个自己写的采用Http做附件上传的工具,分享一下!示例代码:/**
- 背景前些天遇到一个需求,在没有第三方源码的情况下,刷新一个第三方UI,并且拦截到其ajax请求的返回结果。当结果为AVALIABLE的时候,
- 这个CardStackViewpager的灵感来自Github上面的 FlippableStackView开源项目,而我想实现的效果方向上恰
- 需求使用 spring-boot 项目开发中,项目启动时“非常”慢的。如果每次修改代码或静态资源文件后都需要重新启动项目,这是多么痛苦的事。
- 安装 小试记一次使用arthas排查jvm中CPU占用过高问题。这工具 * 爆了 碾压我目前使用的全部JVM工具。curl -O https:/
- 1.什么是接口隔离原则?客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口范围上。2.对应代码上面这张图呢,就违反
- 本文实例讲述了C#图像边缘检测(Roberts)的方法。分享给大家供大家参考。具体如下://定义roberts算子函数private sta
- 数组排序在很多的面试题上都会出现数组排序的操作形式。但是这个时候你千万别写上:java.util.Arrays.sort(数组)。而这种排序
- java的String对象底层是有字符数组存储的,理论上char[] 最大长度是int的最大值,实际思路:首先,String字面
- Web Services 可以将应用程序转换为网络应用程序。通过使用 Web Services,您的应用程序可以向全世界发布信息,或提供某项
- PPT中的动画效果可分为已有内置动画以及自定义动画。设置内置动画,只需直接指定动画效果类型即可。本文主要介绍如何实现自定义动画,即自定义形状