一、概述

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. //1、从URI中获取XML数据,支持本地路径和URL,支持对应枚举的设置
  2. XElement xe1 = XElement.Load(@"D:\123.xml",LoadOptions.None);
  3.  
  4. //2、从XmlReader中加载
  5. XmlReader xr = XmlReader.Create(@"D:\123.xml");
  6. XElement xe2 = XElement.Load(xr);
  7.  
  8. //3、从TextReader中获取数据
  9. TextReader reader = File.OpenText(@"D:\123.xml");
  10. XElement xe3 = XElement.Load(reader);
  11.  
  12. //4、从Stream中读取
  13. XElement xe4 = XElement.Load(new FileStream(@"D:\123.xml", FileMode.Open, FileAccess.Read));

2、从字符串中输入XML数据

  1. string xmlString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Persons><Person><Name>刘备</Name><Age>28</Age></Person></Persons>";
  2. XElement xe = XElement.Parse(xmlString, LoadOptions.SetLineInfo);

三、生成XML元素或XML文档

1、创建XML元素

  1. XElement xml =
  2. new XElement("Persons",
  3. new XElement("Person",
  4. new XElement("Name", "刘备"),
  5. new XElement("Age", "28")
  6. ),
  7. new XElement("Person",
  8. new XElement("Name", "关羽"),
  9. new XElement("Age", "27")
  10. )
  11. );
  12. xml.Save(@"D:\123.xml");

2、创建XML文档

  1. //创建处理指令
  2. XProcessingInstruction instruction = new XProcessingInstruction("xml-stylesheet","href=\"hello.css\" type = \"text/css\"");
  3. //创建声明对象
  4. XDeclaration xDeclaration = new XDeclaration("1.0","GB2312","yes");
  5. //创建文档类型
  6. XDocumentType documentType = new XDocumentType("Person", null, "Person.dtd", null);
  7. //创建XmlCData数据
  8. XCData data = new XCData("<h1>神奇的刘备</h1>");
  9. //创建XDocument文档
  10. XDocument xDoc = new XDocument();
  11. XElement xml =
  12. new XElement("Persons",
  13. new XElement("Person",
  14. new XAttribute("Description", "此人龙凤之姿 天日之表;"),
  15. new XElement("Name", data),
  16. new XElement("Age", "28")
  17. ),
  18. new XElement("Person",
  19. new XElement("Name", "关羽"),
  20. new XElement("Age", "27")
  21. )
  22. );
  23. xDoc.Add(documentType);
  24. xDoc.Add(instruction);
  25. xDoc.Declaration = xDeclaration;
  26. xDoc.Add(xml);
  27.  
  28. xDoc.Save(@"D:\123.xml");

3、Linq查询生成XML

我们实例化一个book的集合

  1. Book[] books = new Book[] {
  2. new Book("Ajax in Action", "Manning", 2005),
  3. new Book("Windows Forms in Action", "Manning", 2006),
  4. new Book("RSS and Atom in Action", "Manning", 2006)
  5. };

如果我们现在想将Year== 2006的集合创建成以下XML格式

  1. <books>
  2. <book title="Windows Forms in Action">
  3. <publisher>Manning</publisher>
  4. </book>
  5. <book title="RSS and Atom in Action">
  6. <publisher>Manning</publisher>
  7. </book>
  8. </books>

采用linq方式

  1. XElement xml = new XElement("books",
  2. from book in books
  3. where book.Year == 2006
  4. select new XElement("book",
  5. new XAttribute("title", book.Title),
  6. new XElement("publisher", book.Publisher)
  7. )
  8. );
  9. // 显示这个XML
  10. Console.WriteLine(xml);

传统方式

  1. XmlDocument doc = new XmlDocument();
  2. XmlElement root = doc.CreateElement("books");
  3. foreach (Book book in books)
  4. {
  5. if (book.Year == 2006)
  6. {
  7. XmlElement element = doc.CreateElement("book");
  8. element.SetAttribute("title", book.Title);
  9. XmlElement publisher = doc.CreateElement("publisher");
  10. publisher.InnerText = book.Publisher;
  11. element.AppendChild(publisher);
  12. root.AppendChild(element);
  13. }
  14. }
  15. doc.AppendChild(root);
  16. // 显示这个XML
  17. doc.Save(Console.Out);

4、属性转出元素

XML文件:

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <Root Data1="123" Data2="456">
  3. <Child1>Content</Child1>
  4. </Root>

您可以编写一些过程代码以便从属性创建元素,然后删除属性

linq方式:

  1. XElement root = XElement.Load("Data.xml");
  2. XElement newTree = new XElement("Root",
  3. root.Element("Child1"),
  4. from att in root.Attributes()
  5. select new XElement(att.Name, (string)att)
  6. );
  7. xml.Save(@"D:\123.xml");

传统方式:

  1. XElement root = XElement.Load("Data.xml");
  2. foreach (XAttribute att in root.Attributes()) {
  3. root.Add(new XElement(att.Name, (string)att));
  4. }
  5. root.Attributes().Remove();

5、XmlDocument转换为XDocument

  1. XmlDocument doc = new XmlDocument();
  2. doc.LoadXml(xmlStr); //xml字符串转成xml文档对象
  3.  
  4. XDocument xdoc = doc.ToXDocument(); //xmldocument转成xdoccument 扩展方法
  5. var eventId = xdoc.Document.Root.Element("EventID"); //根节点下的eventid节点
  6. if (eventId != null)
  7. {
  8. MessageBox.Show(eventId.Value); //15
  9. }

扩展方法

  1. public static class XmlDocumentExtensions
  2. {
  3. public static XDocument ToXDocument(this XmlDocument document)
  4. {
  5. return document.ToXDocument(LoadOptions.None);
  6. }
  7.  
  8. public static XDocument ToXDocument(this XmlDocument document, LoadOptions options)
  9. {
  10. using (XmlNodeReader reader = new XmlNodeReader(document))
  11. {
  12. return XDocument.Load(reader, options);
  13. }
  14. }
  15. }

四、XML数据的输出

 XElement有个Save,这个Save有多种重载,支持将XML数据输入到各处(文件地址,流,TextWriter,XmlWriter)。

  1. XElement xml =
  2. new XElement("Persons",
  3. new XElement("Person",
  4. new XElement("Name", "刘备"),
  5. new XElement("Age", "28")
  6. )
  7. );
  8. //1、输出到文件
  9. xml.Save(@"D:\123.xml");
  1. //2、输出到TextWriter
  2. TextWriter tw = new StringWriter();
  3. //第二个参数SaveOptions枚举支持设置格式,缩进,保留无关重要的空白,去除重复命名空间
  4. xml.Save(tw, SaveOptions.None);
  5. Console.WriteLine(tw);
  1. //3、输出到Stream
  2. using (MemoryStream mem = new MemoryStream())
  3. {
  4. xml.Save(mem);
  5. Console.WriteLine(Encoding.UTF8.GetString(mem.ToArray()));
  6. }
  1. //4、输出到XmlWriter
  2. XmlWriter xw = XmlWriter.Create(@"D:\LinqToXml.xml");
  3. xml.Save(xw);
  1. xw.Flush();

五、查询

  • Element()  :获取当前XML元素的第一个具有指定名称的子元素
  • Elements() :获取当前XML元素的所有子元素,或具有指定名称的所有子元素,返回类型为IEnumerable<XElement>的可用LINQ进行查询的元素集合
  • Attribute():  获取当前XML元素的具有指定名称的属性
  • Attributes(): 获取当前XML元素的所有属性或者具有指定名称的属性, 返回类型为IEnumerable<XAttribute>的LINQ集合

1、查询根元素

  1. IEnumerable<XElement> elements = from e in doc.Elements("Products")
  2. select e;
  3. foreach (XElement e in elements)
  4. {
  5. Console.WriteLine("{0}-{1}", e.Name, e.Value);
  6. }

2、查询节点

  1. var query = from p in doc.Element("Products").Elements("Product")
  2. where (int)p.Element("ProductID") == 1
  1. orderby p.Attribute("ID").Value
  2. select p;
  3.  
  4. query.ToList().ForEach(item =>
  5. {
  6. Console.WriteLine("{0}-{1}-{2}", item.Element("ProductID").Value, item.Element("ProductName").Value, item.Element("UnitPrice").Value);
  7. });

3、查询子孙节点

Descendants轴方法与Elements类型相似,不过Elements只查找当前元素下的直接子节点,而Descendants则会遍历当前元素下任意层级的子元素。

  1. var query = from b in root.Descendants("Book")
  2. select b;
  3. foreach (var item in query)
  4. {
  5. Console.WriteLine(item.Element("ProductName").Value);
  6. }

4、查询属性

  1. var query = from p in xml.Nodes().OfType<XElement>()
  2. where (int)p.Attribute("ID").Value == 1
  3. select new
  4. {
  5. ID = p.Attribute("ID").Value,
  6. ProductID = p.Element("ProductID").Value,
  7. ProductName = p.Element("ProductName").Value
  8. };

5、查询出来填充到List:

  1. XElement root = XElement.Load(@"like.xml");
  2. var query =
  3. from ele in root.Elements("book")
  4. select new { author = ele.Element("author").Value,
  1. price = ele.Element("price").Value
  1. };
  2.  
  3. String xml = null;
  4. foreach (var item in query)
  5. {
  6. xml = xml + item.ToString() + "\n ------- \n";
  7. }

六、操作节点

1、增加节点

  1. Add():    在 XContainer 的子内容的末尾添加内容。
  2. AddFirst(): 在 XContainer 的子内容的开头添加内容。
  3. AddAfterSelf():  在 XNode 后面添加内容。
  4. AddBeforeSelf() :  在 XNode 前面添加内容。
  1. XElement product = new XElement
  2. (
  3. "Product",
  4. new XAttribute("ID", 2),
  5. new XElement("ProductName", "LINQ to Object"),
  6. new XElement("UnitPrice", 20m),
  7. new XElement("Remark", "")
  8. );
  9.  
  10. el.Add(product);

2、修改、替换节点

  • SetAttributeValue(): 设置属性的值。 如果该属性不存在,则创建该属性。 如果值设置为 null,则移除该属性。
  • SetElementValue():  设置子元素的值。 如果该元素不存在,则创建该元素。 如果值设置为 null,则移除该元素。
  • Value:用指定的文本替换元素的内容(子节点)。
  • SetValue():  设置元素的值。
  • ReplaceAll ():   替换元素的所有内容(子节点和属性)。
  • ReplaceAttributes():   替换元素的属性。
  • ReplaceWith():   用新内容替换节点。
  • ReplaceNodes():   用新内容替换子节点。
  1. IEnumerable<XElement> products = from e in el.Elements("Product")
  2. where e.Attribute("ID").Value == "1"
  3. select e;
  4. if (products.Count() > 0)
  5. {
  6. XElement product = products.First();
  7. product.SetAttributeValue("ID", 3);
  8. product.ReplaceNodes
  9. (
  10. new XElement("ProductName", "LINQ to XML Version 2"),
  11. new XElement("UnitPrice", 30)
  12. );
  13. }

3、删除节点

  • RemoveAll():  移除元素的所有内容(子节点和属性)。
  • RemoveAttributes():  移除元素的属性。
  • ReplaceNodes():  删除子节点。
  • Remove():  移除掉整个节点或节点集合
  1. IEnumerable<XElement> products = from e in el.Elements("Product")
  2. where e.Attribute("ID").Value == "2"
  3. select e;
  4. if (products.Count() > 0)
  5. {
  6. products.First().Remove();
  7. }
  8.  
  9. xml.Element("Product").Remove(); // 删除第一个Product子元素
  10. xml.Elements("Product").Remove(); // 删除全部Product子元素
  11.  
  12. xml.SetElementValue("Product", null); // 删除第一个Product子元素
  13.  
  14. xml.Element("Product").SetElementValue("ProductID", 1); // 修改ProductID子元素
  15. xml.Element("Product").SetElementValue("ProductID", null); // 删除ProductID子元素

4、属性操作

  1. //添加属性:
  2. product.Add(new XAttribute("ID", 1));
  3.  
  4. //修改属性:
  5. product.SetAttributeValue("ID", 2);
  6.  
  7. //删除属性:
  8. product.Attribute("ID").Remove();

六、使用XPath查询

为了在LINQ XML中使用XPath查询,需要添加System.Xml.XPath命名空间。如下:

using Sytem.Xml.XPath;

添加了System.Xml.XPath命名空间,XNode类就添加了一系列扩展方法。有了这些扩展方法,我们可以有两种选择处理XML。使我们的应用程序可以进行一个平稳的移植。

  1. CreateNavigator方法,这允许我们从一个现有的XNode对象创建一个XPathNavigator对象。
  2. XPathEvaluate方法允许对XNode上的XPath表达式进行计算。
  3. XPathSelectElement方法返回第一个匹配表达式的元素, XPathSelectElements方法返回所有匹配表达式的元素。

为了查询如下XML数据:

  1. <category name="Technical">
  2. <category name=".NET">
  3. <books>
  4. <book>CLR via C#</book>
  5. <book>Essential .NET</book>
  6. </books>
  7. </category>
  8. <category name="Design">
  9. <books>
  10. <book>Refactoring</book>
  11. <book>Domain Driven Design</book>
  12. <book>Patterns of Enterprise Application Architecture</book>
  13. </books>
  14. </category>
  15. <books>
  16. <book>Extreme Programming Explained</book>
  17. <book>Pragmatic Unit Testing with C#</book>
  18. <book>Head First Design Patterns</book>
  19. </books>
  20. </category>

如何使用XPath查询XML数据:

  1. XElement root = XElement.Load("categorizedBooks.xml");
  2. var books = from book in root.XPathSelectElements("//book")
  3. select book;
  4.  
  5. foreach (XElement book in books)
  6. {
  7. Console.WriteLine((string)book);
  8. }

七、XML进行转换

1、使用XSLT进行转换

  1. string xsl = @"<?xml version='1.0' encoding='UTF-8' ?>
  2. <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>
  3. </xsl:stylesheet>
  1. ";
  2.  
  3. XElement books = XElement.Load("books.xml");
  4. XDocument output = new XDocument();
  5. using (XmlWriter writer = output.CreateWriter())
  6. {
  7. XslCompiledTransform xslTransformer = new XslCompiledTransform();
  8. xslTransformer.Load(XmlReader.Create(new StringReader(xsl)));
  9. xslTransformer.Transform(books.CreateReader(), writer);
  10. }
  11. Console.WriteLine(output);

为了重用转换代码,可以将转换逻辑封装到一个扩展方法中

  1. public static class XmlExtensions
  2. {
  3. public static XDocument XslTransform(this XNode node, string xsl)
  4. {
  5. XDocument output = new XDocument();
  6. using (XmlWriter writer = output.CreateWriter())
  7. {
  8. XslCompiledTransform xslTransformer = new XslCompiledTransform();
  9. xslTransformer.Load(XmlReader.Create(new StringReader(xsl)));
  10. xslTransformer.Transform(node.CreateReader(), writer);
  11. }
  12. return output;
  13. }
  14. }
  15.  
  16. //使用这个扩展方法
  17. XElement.Load("books.xml").XslTransform(xsl));

2、使用 LINQ to XML 转换 XML

XSL 并不是改变 XML 格式的唯一方式(过去它是唯一实际可行的办法),但今天,LINQ to XML 提供了一个富有竞争力的选择。要使用 LINQ to XML 进行转换,你需要一个运用投影的 LINQ 表达式。技巧在于投影必须返回一个 XElement 而不是匿名类型。

  1. string xmlFile = Server.MapPath("DvdList.xml");
  2. XDocument doc = XDocument.Load(xmlFile);
  3.  
  4. XDocument newDoc = new XDocument(
  5. new XDeclaration("1.0", "utf-8", "yes"),
  6. new XElement("Movies",
  7. from DVD in doc.Descendants("DVD")
  8. where (int)DVD.Attribute("ID") < 3
  9. select new XElement[]
  10. {
  11. new XElement ("Moive",
  12. new XAttribute("name", (string)DVD.Element("Title")),
  13. DVD.Descendants("Star")
  14. )
  15. }
  16. )
  17. );
  18.  
  19. string newFile = Server.MapPath("MovieList.xml");
  20. newDoc.Save(newFile);

结果:

  1. <?xml version="1.0" encoding="utf-8" standalone="yes"?>
  2. <Movies>
  3. <Moive name="The Matrix">
  4. <Star>Keanu Reeves</Star>
  5. <Star>Laurence Fishburne</Star>
  6. </Moive>
  7. <Moive name="Forrest Gump">
  8. <Star>Tom Hanks</Star>
  9. <Star>Robin Wright</Star>
  10. </Moive>
  11. </Movies>

基于 LINQ 转换的语法通常要比使用 XSL 样式表的转换更容易理解,并且更加精确你也可以很方便的替换为另一个 IEnumable<T>的集合,包括 LINQ to Entities 获得的结果集,然后随意打包成另一种格式的 XML 文档。

七、Linq To XML:XElement、XDocument的更多相关文章

  1. Linq to XML 之XElement的Descendants方法的新发现

    C#操作XML的方法有很多,但个人认为最方便的莫过于Linq to XML了,特别是XElement的Descendants方法是我最常用的一个方法. 这个方法可以根据节点名(Name)找到当前调用的 ...

  2. [C#]Linq To Xml 实例操作- 转

    http://blog.sina.com.cn/s/blog_6c762bb301010oi5.html http://blog.xuite.net/cppbuilder/blog/9940157 在 ...

  3. LINQ系列:LINQ to XML类

    LINQ to XML由System.Xml.Linq namespace实现,该namespace包含处理XML时用到的所有类.在使用LINQ to XML时需要添加System.Xml.Linq. ...

  4. LINQ系列:LINQ to XML操作

    LINQ to XML操作XML文件的方法,如创建XML文件.添加新的元素到XML文件中.修改XML文件中的元素.删除XML文件中的元素等. 1. 创建XML文件 string xmlFilePath ...

  5. LINQ系列:LINQ to XML查询

    1. 读取XML文件 XDocument和XElement类都提供了导入XML文件的Load()方法,可以读取XML文件的内容,并转换为XDocument或XElement类的实例. 示例XML文件: ...

  6. Linq to Xml读取复杂xml(带命名空间)

    前言:xml的操作方式有多种,但要论使用频繁程度,博主用得最多的还是Linq to xml的方式,觉得它使用起来很方便,就用那么几个方法就能完成简单xml的读写.之前做的一个项目有一个很变态的需求:C ...

  7. [原创]Linq to xml增删改查Linq 入门篇:分分钟带你遨游Linq to xml的世界

    本文原始作者博客 http://www.cnblogs.com/toutou Linq 入门篇(一):分分钟带你遨游linq to xml的世界 本文原创来自博客园 请叫我头头哥的博客, 请尊重版权, ...

  8. Linq对XML的简单操作

    前两章介绍了关于Linq创建.解析SOAP格式的XML,在实际运用中,可能会对xml进行一些其它的操作,比如基础的增删该查,而操作对象首先需要获取对象,针对于DOM操作来说,Linq确实方便了不少,如 ...

  9. LINQ to XML 编程基础

    1.LINQ to XML类 以下的代码演示了如何使用LINQ to XML来快速创建一个xml: 隐藏行号 复制代码 ?创建 XML public static void CreateDocumen ...

随机推荐

  1. eNSP——实现OSPF与ACL综合实验

    OSPF与ACL再前几个随笔中提到了,现在我们来做一个实例. 拓扑图: 实验案例要求: 1.企业内网运行OSPF路由协议,区域规划如图所示:2.财务和研发所在的区域不受其他区域链路不稳定性影响:3.R ...

  2. 伸缩布局 Flex

    其中在webkit内核的浏览器中使用时,必须加上-webkit-前缀,采用Flex布局的元素,称为Flex容器(flex container),简称”容器”.它的所有子元素自动成为容器成员,称为Fle ...

  3. nvidia jetson tx2 刷机遇到的问题解决

    一.主要信息 使用的开发板:nvidia jetson tx2(内存8g有wifi的版本) 使用的JetPack版本: 4.2.2 二.遇到的问题及解决 1. 刷好jetson os 后,开发板一直在 ...

  4. LeetCode 897. 递增顺序查找树(Increasing Order Search Tree)

    897. 递增顺序查找树 897. Increasing Order Search Tree 题目描述 给定一个树,按中序遍历重新排列树,使树中最左边的结点现在是树的根,并且每个结点没有左子结点,只有 ...

  5. nginx tar包安装 包含openssl,rewrite,stream,sticky 等模块

    最近需要使用nginx 但是发现有时缺少一些模块. 所以 在学习如何增加上相应的模块. 主要学习的网站: 沧海书生 Ansible爱好者 https://www.cnblogs.com/tssc/p/ ...

  6. JVM插码之六:jacoco插码及问题“$jacocodata 属性 Method not found: is$jacocoData”

    在使用jacoco统计自动化代码覆盖率 jacoco统计自动化代码覆盖率 1. 简介1.1. 什么是JacocoJacoco是一个开源的代码覆盖率工具,可以嵌入到Ant .Maven中,并提供了Ecl ...

  7. 【Qt】Qt5.12连接MySQl5.7(亲自测试成功)

    目录 00. 目录 01. Qt5.12连接MySQL5.7测试代码 02. Qt5.12连接MySQL5.7问题描述 03. 解决办法 04. 结果测试 05. 打赏 00. 目录 01. Qt5. ...

  8. 软件包 javax.naming了解

    Context  此接口表示一个命名上下文,它由一组名称到对象的绑定组成. Name  Name 接口表示一个一般名称,即一个有序的组件序列. NameParser  此接口用于解析取自分层的名称空间 ...

  9. Ubuntu 利用 mtd-utils 制作ubifs.img

    确保已经安装了有关的工具 sudo apt-get install mtd-utils mkfs.ubifs -d fs -m -o rootfslink.ubiimg -e -c -F -v syn ...

  10. windows Git Bash 无法运行python文件的解决方法(转)

    https://blog.csdn.net/xie_0723/article/details/51958243