C#中的Linq To XML讲解

一、概述

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 文档。

到此这篇关于C#中Linq To XML的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C# LINQ to XML应用介绍

    W3C制定了XML DOM标准,.Net为了支持W3C的标准,从1.1版本开始就引入了XmlDocument类.我在前一篇博客中,介绍了如何使用XmlDocument类来对XML文档进行操作.后来 .Net又引入了LINQ,于是LINQ to XML也就应运而生,所以在.Net中,不仅可以用W3C XML DOM标准,还可以使用LINQ to XML来操作XML文档.下面就来简单介绍一下如何使用LINQ to XML. (一) 加载 加载XML比较常用的有三种方法: 复制代码 代码如下: pub

  • C#中利用LINQ to XML与反射把任意类型的泛型集合转换成XML格式字符串的方法

    在工作中,如果需要跟XML打交道,难免会遇到需要把一个类型集合转换成XML格式的情况.之前的方法比较笨拙,需要给不同的类型,各自写一个转换的函数.但是后来接触反射后,就知道可以利用反射去读取一个类型的所有成员,也就意味着可以替不同的类型,创建更通用的方法.这个例子是这样做的:利用反射,读取一个类型的所有属性,然后再把属性转换成XML元素的属性或者子元素.下面注释比较完整,就话不多说了,有需要看代码吧! using System; using System.Collections.Generic;

  • C#中的Linq to Xml详解

    前言 我相信很多从事.NET开发的,在.NET 3.5之前操作XML会比较麻烦,但是在此之后出现了Linq to Xml,而今天的主人公就是Linq to Xml,废话不多说,直接进入主题. 一.生成Xml 为了能够在结构有一定的组织,笔者建议大家新建一个控制台项目,并且新建一个CreateXml类(以下部分都属于该类中). 并在其中写入以下属性: 复制代码 代码如下: public static String Path         {             get            

  • C#程序中使用LINQ to XML来查询XML格式数据的实例

    关于LINQ to XML LINQ to XML 是一种启用了 LINQ 的内存 XML 编程接口,使用它,可以在 .NET Framework 编程语言中处理 XML. 它将 XML 文档置于内存中,这一点很像文档对象模型 (DOM). 您可以查询和修改 XML 文档,修改之后,可以将其另存为文件,也可以将其序列化然后通过网络发送. 但是,LINQ to XML 与 DOM 不同: 它提供一种新的对象模型,这是一种更轻量的模型,使用也更方便,这种模型利用了 VisualC# 2008 在语言

  • C#中的Linq To XML讲解

    一.概述 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类.一个元素就

  • LINQ to XML的编程基础

    一.LINQ to XML 编程基础 1.LINQ to XML类 System.Xml.Linq命名空间含有19个类,下表列出了它们的名称及其描述: 类 描述 XAttribute 表示一个 XML 属性 XCData 表示一个 CDATA 文本节点 XComment 表示一个 XML 注释 XContainer 适用于可能具有子节点的所有节点的抽象基类 XDeclaration 表示一个 XML 声明 XDocument 表示一个 XML 文档 XDocumentType 表示一个 XML

  • java中使用sax解析xml的解决方法

    在java中,原生解析xml文档的方式有两种,分别是:Dom解析和Sax解析 Dom解析功能强大,可增删改查,操作时会将xml文档以文档对象的方式读取到内存中,因此适用于小文档 Sax解析是从头到尾逐行逐个元素读取内容,修改较为不便,但适用于只读的大文档 本文主要讲解Sax解析,其余放在后面 Sax采用事件驱动的方式解析文档.简单点说,如同在电影院看电影一样,从头到尾看一遍就完了,不能回退(Dom可来来回回读取) 在看电影的过程中,每遇到一个情节,一段泪水,一次擦肩,你都会调动大脑和神经去接收或

  • 解析在.net中使用XSLT转换xml文档的示例详解

    XSL即可扩展的样式表文件. 可以格式化xml的显示,也可以将xml转换成需要的另一种格式.学习XSL必须熟悉XPath.XSL和XPath一样简单强大,容易学习.1. XSL既然可以格式化xml的显示样式,我们先来看如何在xml中引用xsl文件如下代码示例:<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="url.

  • 基于spring中的aop简单实例讲解

    aop,即面向切面编程,面向切面编程的目标就是分离关注点,比如:一个骑士只需要关注守护安全,或者远征,而骑士辉煌一生的事迹由谁来记录和歌颂呢,当然不会是自己了,这个完全可以由诗人去歌颂,比如当骑士出征的时候诗人可以去欢送,当骑士英勇牺牲的时候,诗人可以写诗歌颂骑士的一生.那么骑士只需要关注怎么打仗就好了.而诗人也只需要关注写诗歌颂和欢送就好了,那么这样就把功能分离了.所以可以把诗人当成一个切面,当骑士出征的前后诗人分别负责欢送和写诗歌颂(记录).而且,这个切面可以对多个骑士或者明人使用,并不只局

  • asp.net Linq to Xml学习笔记

    加上之前学习过Linq to Entity,因此学习起来也比较随心应手. 以下是项目中某个底层的代码,记下做个备忘,如果能给新手学习Linq to Xml带来帮助,那就再好不过了 XML文件的格式: 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?> <configuration> <OPsystemConfig> <MemberCenter> <DomainNam

随机推荐