七、Linq To XML:XElement、XDocument
一、概述
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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Persons><Person><Name>刘备</Name><Age>28</Age></Person></Persons>";
- 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("<h1>神奇的刘备</h1>");
- //创建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<XElement>的可用LINQ进行查询的元素集合
- Attribute(): 获取当前XML元素的具有指定名称的属性
- Attributes(): 获取当前XML元素的所有属性或者具有指定名称的属性, 返回类型为IEnumerable<XAttribute>的LINQ集合
1、查询根元素
- IEnumerable<XElement> 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<XElement>()
- 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<XElement> 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<XElement> 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 = @"<?xml version='1.0' encoding='UTF-8' ?>
- <xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> <xsl:template match='books'> <html> <title>Book Catalog</title> <ul> <xsl:apply-templates select='book'/>
</ul>
</html> </xsl:template> <xsl:template match='book'> <li>
<xsl:value-of select='title'/> by <xsl:apply-templates select='author'/> </li> </xsl:template> <xsl:template match='author'> <xsl:if test='position() > 1'>, </xsl:if> <xsl:value-of select='.'/> </xsl:template>- </xsl:stylesheet>
- ";
- 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<T>的集合,包括 LINQ to Entities 获得的结果集,然后随意打包成另一种格式的 XML 文档。
七、Linq To XML:XElement、XDocument的更多相关文章
- Linq to XML 之XElement的Descendants方法的新发现
C#操作XML的方法有很多,但个人认为最方便的莫过于Linq to XML了,特别是XElement的Descendants方法是我最常用的一个方法. 这个方法可以根据节点名(Name)找到当前调用的 ...
- [C#]Linq To Xml 实例操作- 转
http://blog.sina.com.cn/s/blog_6c762bb301010oi5.html http://blog.xuite.net/cppbuilder/blog/9940157 在 ...
- LINQ系列:LINQ to XML类
LINQ to XML由System.Xml.Linq namespace实现,该namespace包含处理XML时用到的所有类.在使用LINQ to XML时需要添加System.Xml.Linq. ...
- LINQ系列:LINQ to XML操作
LINQ to XML操作XML文件的方法,如创建XML文件.添加新的元素到XML文件中.修改XML文件中的元素.删除XML文件中的元素等. 1. 创建XML文件 string xmlFilePath ...
- LINQ系列:LINQ to XML查询
1. 读取XML文件 XDocument和XElement类都提供了导入XML文件的Load()方法,可以读取XML文件的内容,并转换为XDocument或XElement类的实例. 示例XML文件: ...
- Linq to Xml读取复杂xml(带命名空间)
前言:xml的操作方式有多种,但要论使用频繁程度,博主用得最多的还是Linq to xml的方式,觉得它使用起来很方便,就用那么几个方法就能完成简单xml的读写.之前做的一个项目有一个很变态的需求:C ...
- [原创]Linq to xml增删改查Linq 入门篇:分分钟带你遨游Linq to xml的世界
本文原始作者博客 http://www.cnblogs.com/toutou Linq 入门篇(一):分分钟带你遨游linq to xml的世界 本文原创来自博客园 请叫我头头哥的博客, 请尊重版权, ...
- Linq对XML的简单操作
前两章介绍了关于Linq创建.解析SOAP格式的XML,在实际运用中,可能会对xml进行一些其它的操作,比如基础的增删该查,而操作对象首先需要获取对象,针对于DOM操作来说,Linq确实方便了不少,如 ...
- LINQ to XML 编程基础
1.LINQ to XML类 以下的代码演示了如何使用LINQ to XML来快速创建一个xml: 隐藏行号 复制代码 ?创建 XML public static void CreateDocumen ...
随机推荐
- eNSP——实现OSPF与ACL综合实验
OSPF与ACL再前几个随笔中提到了,现在我们来做一个实例. 拓扑图: 实验案例要求: 1.企业内网运行OSPF路由协议,区域规划如图所示:2.财务和研发所在的区域不受其他区域链路不稳定性影响:3.R ...
- 伸缩布局 Flex
其中在webkit内核的浏览器中使用时,必须加上-webkit-前缀,采用Flex布局的元素,称为Flex容器(flex container),简称”容器”.它的所有子元素自动成为容器成员,称为Fle ...
- nvidia jetson tx2 刷机遇到的问题解决
一.主要信息 使用的开发板:nvidia jetson tx2(内存8g有wifi的版本) 使用的JetPack版本: 4.2.2 二.遇到的问题及解决 1. 刷好jetson os 后,开发板一直在 ...
- LeetCode 897. 递增顺序查找树(Increasing Order Search Tree)
897. 递增顺序查找树 897. Increasing Order Search Tree 题目描述 给定一个树,按中序遍历重新排列树,使树中最左边的结点现在是树的根,并且每个结点没有左子结点,只有 ...
- nginx tar包安装 包含openssl,rewrite,stream,sticky 等模块
最近需要使用nginx 但是发现有时缺少一些模块. 所以 在学习如何增加上相应的模块. 主要学习的网站: 沧海书生 Ansible爱好者 https://www.cnblogs.com/tssc/p/ ...
- JVM插码之六:jacoco插码及问题“$jacocodata 属性 Method not found: is$jacocoData”
在使用jacoco统计自动化代码覆盖率 jacoco统计自动化代码覆盖率 1. 简介1.1. 什么是JacocoJacoco是一个开源的代码覆盖率工具,可以嵌入到Ant .Maven中,并提供了Ecl ...
- 【Qt】Qt5.12连接MySQl5.7(亲自测试成功)
目录 00. 目录 01. Qt5.12连接MySQL5.7测试代码 02. Qt5.12连接MySQL5.7问题描述 03. 解决办法 04. 结果测试 05. 打赏 00. 目录 01. Qt5. ...
- 软件包 javax.naming了解
Context 此接口表示一个命名上下文,它由一组名称到对象的绑定组成. Name Name 接口表示一个一般名称,即一个有序的组件序列. NameParser 此接口用于解析取自分层的名称空间 ...
- Ubuntu 利用 mtd-utils 制作ubifs.img
确保已经安装了有关的工具 sudo apt-get install mtd-utils mkfs.ubifs -d fs -m -o rootfslink.ubiimg -e -c -F -v syn ...
- windows Git Bash 无法运行python文件的解决方法(转)
https://blog.csdn.net/xie_0723/article/details/51958243