C#操作XML(三)

C#进入3.0时代,引入了强大的LINQ,同时提供了Linq to Xml,这个全新的Xml Api。与Inq to Xml相比,传统的DOM Api就显得笨重而繁杂了。

一、Linq to Xml的本质

  首先,Linq to Xml是一种in-memory的技术,也就是说,如果用Linq to Xml去打开一个Xml,也就会占用相应的内存。所以和DOM一样,在极端的情况下,会出现内存不足。

  其次,Linq to Xml从本质上来说,就是Linq to Object+一套Xml Api,与Linq to Sql和Linq to entity framework不同,后两者是使用特定的Linq Provider去翻译成对应系统的语言。

  Linq to Xml和DOM都是用in-memory的方式操作Xml的。

二、使用Linq to Xml操作无Namespace的Xml.

1. 创建Xml

  创建如下Xml:

<?xml version="1.0" encoding="utf-8" ?>
<persons>
  <person>
    <firstName>Zhenway</firstName>
    <lastName>Yan</lastName>
    <address>http://www.baidu.com/</address>
  </person>
  <person>
    <firstName>Allen</firstName>
    <lastName>Lee</lastName>
    <address>http://www.baidu.com/</address>
  </person>
</persons>

  C#代码:

    方法1:

XDocument doc = new XDocument(
    new XDeclaration("1.0", "UTF-8", null),
    new XElement("persons",
        new XElement("person",
              new XElement("firstName", "Zhenway"),
              new XElement("lastName", "Yan"),
              new XElement("address", "http://www.baidu.com/")
              ),
              new XElement("person",
              new XElement("firstName", "Allen"),
              new XElement("lastName", "Lee"),
              new XElement("address", "http://www.baidu.com/")
              )
         )
    );    

    方法2:

var persons = new[]
{
    new
    {
        FirstName = "Zhenway",
        LastName = "Yan",
        Address = "http://www.baidu.com/"
     },
    new
    {
         FirstName = "Allen",
         LastName = "Lee",
         Address = "http://www.baidu.com//"
     }
};

XDocument doc = new XDocument(
    new XDeclaration("1.0", "UTF-8", null),
    new XElement("persons",
        from person in persons
        select new XElement("person",
            new XElement("firstName", person.FirstName),
            new XElement("lastName", person.LastName),
            new XElement("address", person.Address))
         )
);                 

2. 查询Xml

  a. 一个简单的查询

XDocument doc = XDocument.Parse(@"<?xml version=""1.0"" encoding=""utf-8""?>
<persons>
  <person>
    <firstName>Zhenway</firstName>
    <lastName>Yan</lastName>
    <address>http://www.cnblogs.com/</address>
  </person>
  <person>
    <firstName>Allen</firstName>
    <lastName>Lee</lastName>
    <address>http://www.cnblogs.com/</address>
  </person>
</persons>");
foreach (var item in doc.Root.Descendants("address"))
{
    Console.WriteLine((string)item);
}

  注意:Desendats方法的签名:public IEnumerable<XElement> Descendants(XName name);

     参数类型是XName,而传入的是一个string,为什么合法呢?来看一下XName中的一个定义:

     public static implicit operator XName(string expandedName);

       原来有一个隐式转换,这样就好理解了,编译器自动调用了隐式转换。

  b. 一个复杂的查询

  查询firstName为“Zhenway”的person节点中的address节点:

XDocument doc = XDocument.Parse(@"<?xml version=""1.0"" encoding=""utf-8""?>
<persons>
  <person>
    <firstName>Zhenway</firstName>
    <lastName>Yan</lastName>
    <address>http://www.cnblogs.com/</address>
  </person>
  <person>
    <firstName>Allen</firstName>
    <lastName>Lee</lastName>
    <address>http://www.cnblogs.com/</address>
  </person>
</persons>");
foreach (var item in from person in doc.Root.Descendants("person")
                           where (string)person.Element("firstName") == "Zhenway"
                           select (string)person.Element("address"))
{
    Console.WriteLine((string)item);
}    

三、使用Linq to Xml操作有Namespace的Xml

1. 设置目标

  目标:创建一个这样的Xml:

<?xml version="1.0" encoding="utf-8" ?>
<v:persons xmlns:v="http://www.cnblogs.com/">
  <v:person>
    <v:firstName>Zhenway</v:firstName>
    <v:lastName>Yan</v:lastName>
    <v:address>http://www.cnblogs.com/</v:address>
  </v:person>
</v:persons>

  注意:这个Xml的每一个节点都是在http://www.cnblogs.com/这个命名空间下。

  关于Xml的命名空间也有很多种等效写法,具体请参考w3schools。

2. 分析实现手段

  a. 这里的"persons"不再是一个纯粹的"persons",而是一个带有Namespace的persons,需要修改成带有Namespace的节点名。

  b. 那么如何获得这个带有Namesapce的节点名呢?

    让我们回过头来看看XElement的构造函数:

      public XElement (XName name);

      注意:参数的类型是XName,而不是string,那么平时为什么能用string呢?因为上一篇里面提到过,XName定义了一个隐式类型转换,可以把string隐式转换为XName。

      同理,关于Namespace自然也要从XNamespace入手,然后找一个能够变成XName的方法,查看XNamespace的定义,就可以看到:

     public static XName operator +(XNamespace ns, string localName);

    只要把XNamespace加上本地名称(string),就可以是一个XName了,非常简单。

    再看看如何创建一个XNamespace:

     public static implicit operator XNamespace(string namespaceName);

      又是隐式转换...来看看具体如何创建一个带有namespace的persons吧:  

XNamespace v = "http://www.cnblogs.com/";
var persons = new XElement(v + "persons");

     定义一个namespace,在使用时直接+string即可。在C#里面这已经是最简单的方式了。

3. 创建Xml

  实现:  

XNamespace v = "http://www.cnblogs.com/";
XDocument doc = new XDocument(
    new XDeclaration("1.0", "utf-8", null),
    new XElement(v + "persons",
        new XElement(v + "persons",
            new XElement(v + "firstName", "Zhenway"),
            new XElement(v + "lastName", "Yan"),
            new XElement(v + "address", "http://www.cnblogs.con/")
            )
        )
);
doc.Save(Console.Out);                    

  结果:

<?xml version="1.0" encoding="gb2312"?>
<persons xmlns="http://www.cnblogs.comh/">
  <person>
    <firstName>Zhenway</firstName>
    <lastName>Yan</lastName>
    <address>http://www.cnblogs.com/</address>
  </person>
</persons>

  和预期的略有不同,首先encoding被修改成gb2312,这是因为中文操作系统的Console的编码是gb2312,所以Xml的encoding被自动修改了,其次,原来的Namespace用v来缩写,但是输出的xml缺是改用了默认Namespace,不过如果看过前面提到的w3schools的话,就知道这两者是等价xml。

4. 查询Xml

  在查找一个Xml时,同样也需要一个XName,因此当遇到带Namespace的Xml,也可以用同样的手法:  

XDocument doc = XDocument.Parse(@"<?xml version=""1.0"" encoding=""utf-8"" ?>
<v:persons xmlns:v=""http://www.cnblogs.com/"">
  <v:person>
    <v:firstName>Zhenway</v:firstName>
    <v:lastName>Yan</v:lastName>
    <v:address>http://www.cnblogs.com/</v:address>
  </v:person>
  <v:person>
    <v:firstName>Allen</v:firstName>
    <v:lastName>Lee</v:lastName>
    <v:address>http://www.cnblogs.com/</v:address>
  </v:person>
</v:persons>");
XNamespace v = "http://www.cnblogs.com/";
foreach (var item in from person in doc.Root.Descendants(v + "person")
                           where (string)person.Element(v + "firstName") == "Zhenway"
                           select (string)person.Element(v + "address"))
{
        Console.WriteLine(item);
}

四、总结

  无论是DOM Api还是Linq to Xml都是In-Memory的工作方式,这样的工作方式对内存的要求相对较高,而且不适合超大Xml文件的处理(会导致内存溢出)。

时间: 2024-10-30 03:27:34

C#操作XML(三)的相关文章

JavaScript操作XML工作记录

JavaScript操作XML (一) JavaScript操作XML是通过XML DOM来完成的.那么什么是XML DOM呢?XML DOM 是: 用于 XML 的标准对象模型 用于 XML 的标准编程接口 中立于平台和语言 W3C 的标准 XML DOM 定义了所有XML 元素的对象和属性,以及访问它们的方法(接口).也就是说:XML DOM 是用于查询.添加.修改.删除XML 元素的标准. 在继续之前,我们先来了解一下XML的定义.请看下面的 XML 文件 (books.xml):<?xm

XML编程总结(三)——使用SAX接口操作xml

(三)使用SAX接口操作xml SAX解析器被称为SAXParser,SAXParser是由javax.xml.parsers.SAXParserFactory创建的.与DOM解析器不同,SAX解析器并不创建XML文档的内存表示,因此会占用更少的内存.SAX解析器通过调用回调方法(事件驱动)将XML文档结构通知客户端,也就是通过调用提供给SAXParser的org.xml.sax.helpers.DefaultHandler处理器内的方法. org.xml.sax.helpers.Default

C#学习笔记(12)——三种方法操作XML

说明(2017-7-11 16:56:13): 原文地址: C#中常用的几种读取XML文件的方法 XML文件是一种常用的文件格式,例如WinForm里面的app.config以及Web程序中的web.config文件,还有许多重要的场所都有它的身影.Xml是Internet环境中跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有力工具.XML是一种简单的数据存储语言,使用一系列简单的标记描述数据,而这些标记可以用方便的方式建立,虽然XML占用的空间比二进制数据要占用更多的空间,但XML极其

delphi操作xml学习笔记 之一 入门必读

Delphi 对XML的支持---TXMLDocument类 Delphi7 支持对XML文档的操作,可以通过TXMLDocument类来实现对XML文档的读写.可以利用TXMLDocument把XML文档读到内存中,从而可以进行编辑.保存操作.TXMLDocument类是通过DOM(文档对象模型)接口来访问XML文档中的各个元素的.对于DOM接口的实现有多种方式,Delphi支持的方式有:1)微软的MSXML SDK,这种方式是通过COM对象来实现:2) Apache 的Xerces的实现方式

Delphi 操作 XML(一)

一.欢迎 本帮助文件提供从SimDesign BV的NativeXml组件的信息. 二.购买NativeXml! NativeXml现在是开源的,但支持是仅专门适用于购买NativeXml的客户. 您可以通过此链接购买NativeXml:http://www.simdesign.nl/xml.html 价格:29.95欧元 采购NativeXml的优势: 两年的通过电子邮件或特殊的"NativeXml Source"论坛支持,接收测试和修正,并从"NativeXml Sour

Delphi操作XML简介

参考:http://www.delphifans.com/InfoView/Article_850.html Delphi 7支持对XML文档的操作,可以通过 TXMLDocument类来实现对XML文档的读写.可以利用TXMLDocument把XML文档读到内存中,从而可以进行编辑.保存操作.TXMLDocument类是通过DOM(文档对象模型)接口来访问XML文档中的各个元素的.对于DOM接口的实现有多种方式,Delphi 支持的方式有 1)微软的MSXML SDK,这种方式是通过COM对象

PHP操作XML详解

XML是一种流行的半结构化文件格式,以一种类似数据库的格式存储数据.在实际应用中,一些简单的.安全性较低的 数据往往使用 XML文件的格式进行存储.这样做的好处一方面可以通过减少与数据库的交互性操作提高读取效率,另一方面可以有效利用 XML的优越性降低程序的编写难度.        PHP提供了一整套的读取 XML文件的方法,很容易的就可以编写基于 XML的脚本程序.本章将要介绍 PHP与 XML的操作方法,并对几个常用的 XML类库做一些简要介绍. 1 XML简介 XML是“可扩展性标识语言(

JavaScript操作XML(二)

上一篇介绍了XML的结构以及节点之间的关系这一篇介绍浏览器内建的XML解析器以及JavaScript是如何加载XML的. 大多数浏览器都有读取和操作 XML 的内建 XML 解析器. 解析器(XML Parser)把 XML 转换为 JavaScript 可访问的对象. 解析器把 XML 载入内存,然后把它转换为可通过 JavaScript 访问的 XML DOM 对象. 微软的 XML 解析器与其他浏览器中的解析器之间,存在一些差异.微软的解析器支持 XML 文件和 XML 字符串(文本)的加

C#操作XML(读XML,写XML,更新,删除节点,与dataset结合等)【转载】

已知有一个XML文件(bookstore.xml)如下: Corets, Eva 5.95 1.插入节点 往节点中插入一个节点: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 XmlDocument xmlDoc=new XmlDocument(); xmlDoc.Load("bookstore.xml"); XmlNode root=xmlDoc.SelectSingleNode("bookstore");//查找