Linq to XML相关内容的介绍

XML(EXensible Markup Language),可扩展标记语言。

本文并不对它的概念进行详细介绍,取而代之的是说说在.Net下怎么去操作XML文件。点一下题外话,XML是标准通用标记语言(SGML)的子集,可以跨平台运行,非常适合Web传输,在不同的编程语言(PHP、Java、.Net等)里面都有广泛运用,所以对于XML的操作,将是你必须掌握的一门技术。

下面我们来看看XML文档是长什么样子的,这里将要以下图为例来进行说明。XML可以用来描述数据定义、类型等,它一般是被用作数据存储和数据传输。

 

                                                                                                               图 一

用下面的方法可以生成上面xml的文件,生成一个xml的文件,可以用到XDocument里面的Save方法,也可以用到XElement里面的Save方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace LinqToXml2
{
    class Program
    {
        static void Main(string[] args)
        {
            XDocument doc = new XDocument(
                new XDeclaration("1.0", "UTF-8", "true"),
                new XElement("Root00",
                    new XElement("Root10",
                        new XAttribute("color", "Green"), "椭圆"),
                    new XElement("Root11",
                        new XAttribute("color", "White"),
                        new XAttribute("value", "四边形"),
                        new XElement("Root20",
                            new XAttribute("color", "Purple"), "菱形"
                            ),
                        new XElement("Root21",
                            new XAttribute("color", "Red"), "梯形")),
                    new XElement("Root12",
                        new XAttribute("color", "Orange"), "三角形")
                        )
                    );

            doc.Save("../../Shape.xml");//用此方法来保存xml文档到文件当中
        }
    }
}

注:这里讲一下,保存的路径问题,它代表的是上上级的目录,因为在控制台应用程序默认的环境里面运行的话,它是位于工程Bin目录里的Debug目录里面,所以它的上两级目录就刚好是根目录,而我们放置的shape.xml就在根目录里面。而对于像Server.MapPath和HttpContext.Current.Server.MapPath则可以简单根据如下的总结方式来使用,如下的总结我是根据网上的资料来进行汇总,有什么不对的话,欢迎指出。

1.定义一个继承于Page类的页面代码,这里就包括是aspx.cs和在aspx页面里面,因为aspx和aspx.cs都是同一个局部类,这种情况都可以使用Server.MapPath。因为Server.MapPath的全写是:this.Page.Server.MapPath。


2.在继承于Page的类里(.cs)使用 HttpContext.Current.Server.MapPath,因为这个类没有页面的实例化,不能指定到具体的页面,this.Page.Server.MapPath,一个是通过对象调用(this),一个是通过类调用(HttpContext.Current,(当前页面)),因为使用HttpContext.Current的时候,Page类一般还没有被实例化。

最终生成的数据内容如下:(保存为Shape.xml):

<?xml version="1.0" encoding="utf-8"?>
<Root00>
  <Root10 color="Green">椭圆</Root10>
  <Root11 color="White" value="四边形">
    <Root20 color="Purple">菱形</Root20>
    <Root21 color="Red">梯形</Root21>
  </Root11>
  <Root12 color="Orange">三角形</Root12>
</Root00>

这里简单介绍下:

第一句( <?xml version="1.0" encoding="utf-8"?> ),这是声明为XML的语句,它的作用就是告诉浏览器将要处理的文档是XML文件。但是XML声明在XML文档里面是可选的,也就是说不出现XML的声明语句,有时候也是可以的。但是在我们这里就不可以了,因为我们的XML文档里面包含中文(中文的编码是GBK、GB2312或者是utf-8),如果声明的话,在浏览器里面打开会报错。
 
第二句(<Root00>…</Root00> ),这个就是根元素,在一个XML文档里面它是惟一的一个,它是所有元素的父级元素。
 
第三句( <Root10 color="Green">椭圆</Root10> ),这里面Root10是根元素Root00的子元素,color是Root10的性,Green是属性值,而椭圆是元素值。这里面很容易理解,属性是在元素的尖括号里面,而元素值是处在元素的两之间。因为属性可以是多个,而元素值就一个,所以这么设计应该也是很容易记忆的。后面的语句跟前面的基本相似,这里面我想讲的只是父元素、子元素,这些都只是相对的。比如说Root11跟Root00来比的话,Root11是子元素,而去跟Root20或者是Root21来比的话,Root11是父元素。
 
好了,双击Shape.xml,你可以看到下图的显示结果:
图 二
可以看得出来,这跟我们在xml文件里面写的是没什么两样的吧。这里面我已经把xml一些术语都在第一张图里面标注出来,比如根元素元素属性,这些在图一里面已经有相应的内容。其实XML里面还包含很多别的内容,只是本文介绍的内容比较基础,不涉及的内容就不作说明。
 
在.Net里面,对于XML文档的操作,有好几种实现方式。限于篇幅,这里面只介绍Linq To XML的方式。
 
首先主要介绍下System.linq.xml动态类库里面的一些常用的使用方法,网上的链接地址为System.Xml.Linq命名空间,这里面你可以看MSDN里面的详细说明来帮你进一步理解。

图三

从上图你可以看到System.Xml.Linq.XObject类是Linq To XML的基类,它是一个抽象类。

System.Xml.Linq.XAttribute和System.Xml.XNode类都继承于XObject类。XObject包含的构造函数、属性和方法,这里就不再一一列出,因为它还不是我们这里要介绍的内容。如果大家想进一步学习的话,可以查看MSDN的相关帮助文档。

                                                                                                         图四

之所以贴出图三和图四,是因为我们下面将要介绍的内容都是继承于这两个抽象类(XObject和XContainer)。分别是操作属性的类XAttribute,操作元素的类XElement和操作文档的类XDocument。

首先介绍的是XDocument和XElement类,这两个类其实是比较相像的。因为它们两者都是继承于XContainer抽象类。所以它们二者都具有抽象类XContainer具有的属性和方法。XDocument表示的是XML文档,而XElement表示的是XML元素。这里只介绍它们的一个静态函数Load。这里面将会从简单的例子入手来介绍这些常用方法的使用。这里面我们将加载上文介绍的shape.xml文件。下面来看简单的控制台代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
 
namespace LinqToXml2
{
    class Program
    {
        static void Main(string[] args)
        {
 
            XDocument shapeDoc = XDocument.Load("../../Shape.xml");
            Console.WriteLine(shapeDoc);
 
 
            //XElement shapeElement = XDocument.Load("../../Shape.xml");
            //Console.WriteLine(shapeElement);
 
        }
    }
}

 关于XDocument类和XElement类的静态Load方法,前者返回的是一个XDocument(XML文档)对象,后者(被注释的语句)返回的是一个XElement(XML元素)对象。上面的代码都是从XML文件里面加载内容,不过需要注意的是,XDocument的加载方式与XElement的加载方式,单从元素上来讲的话,XDocument的加载包含了根元素。

这两种不同的加载方式,你可以选择需要的方式来对XML文件进行相应内容的加载。一般来讲,我们常用的方式是元素的加载,因为这样,我们可以直接对元素进行操作。上面的方式是生成一个XML文档和加载需要操作的对象,下面将逐一以简单的方式来实现Linq To XML的增删改查实例。并对里面一些常用的方法做简单的说明。

using System; 
using System.Collections.Generic;
using System.Linq; 
using System.Text; 
using System.Xml;
using System.Xml.Linq;
 
namespace LinqToXml2 {
 
    class Program {
 
        static void Main(string[] args) {
 
            XElement doc = XElement.Load("../../Shape.xml");
            IEnumerable<XElement> elements = doc.Elements();
 
            foreach (var elment in elements) {
                Console.WriteLine(elment.ToString());
            }
 
            Console.Read();
    
        }
    }
} 

查询,这是遍历XML文档里面的元素,这里面输出的结果如下所示。

<Root10 color="Green">椭圆</Root10>
<Root11 color="White" value="四边形"> 
  <Root20 color="Purple">菱形</Root20>
  <Root21 color="Red">梯形</Root21>
</Root11>
<Root12 color="Orange">三角形</Root12> 

对比原先的XML文档(Shape.xml),我们能看到Elements()方法返回的结点并不包含根结点Root00,其实用Element(“元素名")也同样取不到根结点。 Element(“元素名"),是获取具有指定元素名的第一个(按文档顺序)子元素。这里面所说的第一个子元素,是指包含有多个相同元素名的子元素时,只取第一个子元素。这里面根元素下面的元素才被认为是子元素,根元素并不是子元素。当然,第一个子元素,并不是指只有一个元素。可以是元素里面包含别的元素。 而Elements()方法,是按文档顺序返回此元素或文档的子元素集合。很显然,生成一个XElement对象可有两种方式实现。一种是从文档里面加载进来,用这种方式的话,Elements()方法返回文档的子元素集合。注意的是,根元素并不是子元素,这里不返回根元素;另一种方式是通过New XElement()的方式来生成XElement对象,这样的话,它返回的将会是此元素。这种就不需要考虑根元素的情况。

增:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace LinqToXml2
{

    class Program
    {
        static void Main(string[] args)
        {
            XElement doc = XElement.Load("../../Shape.xml");

            XElement add = new XElement("Root13", new XAttribute("Color", "Yellow"), "星形");
            doc.Add(add);

            //doc.Element("Root10").AddBeforeSelf(add); 
            //doc.Element("Root10").AddAfterSelf(add);

            var elements = from e in doc.Elements()
                           select (e);

            foreach (var elment in elements)
            {
                Console.WriteLine(elment);
            }

            Console.Read();
        }
    }
}

上面是简单的添加XML元素的方式,首先来介绍增加XML元素的方法。首先介绍Add(Object)方法,此方法将指定的内容添加为XContainer的子级。这里说的XContainer,是指继承自XContainer。而XDocument和XElement都继承自XConatainer。XContainer的子级,我的理解是根元素的子级。不知道有没有错?

这里面也介绍另外的两个添加的方法,分别是:AddAfterSelt(Object)方法和AddBeforeSelf(Object)方法。前者是在紧跟此节点之后添加指定的内容,而后者是紧跟此节点之后添加指定的内容。这两方法的使用可见上面的注释。它们的使用需要你先定位到某一节点(就像上文中的doc.Element("Root10").AddAfterSelf(add);),然后才能选择是在此节点的前面还是后面增加。下面的显示结果就不再重复罗列出来,因为上面的代码在控制台里面运行一下就会有结果了。

删:

using System;
using System.Collections.Generic; 
using System.Linq;
using System.Text; 
using System.Xml;
using System.Xml.Linq;
 
namespace LinqToXml2 {
 
    class Program {
 
        static void Main(string[] args) {

            XElement doc = XElement.Load("../../Shape.xml");
            //var elements = from e in doc.Elements()
                                // where (e.Element("Root12").Value == "三角形") 
                                // select(e);
            // elements.Remove();
 
            doc.Element("Root11").Element("Root21").Remove();
            Console.WriteLine(doc); Console.Read();
        }
    }
}

删除节点,就是使用XElement的Remove()方法,MSDN给出的中文说明是:从节点的父级中删除此节点。说白了,就是该节点被删除掉了,但是如果是根节点的话,就不会被删除,只会是子节点被删除。大家可以看看上面两种删除的语句,其中注释的删除,是比较受限制的方式,而注释下面的通过一个节点到下一个结点这样的方式来定位删除,这种方式就比较灵活。

改:

using System;
using System.Collections.Generic; 
using System.Linq; 
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace LinqToXml2 {

    class Program {

        static void Main(string[] args) {

            XElement doc = XElement.Load("../../Shape.xml"); 
            doc.Element("Root11").SetElementValue("Root21","方形");

            //(1)doc.Element("Root11").Element("Root21").SetAttributeValue("color", "Blue");

            //(2)doc.Element("Root11").Element("Root21").ReplaceWith(new XElement("Root22","方形"));

            Console.WriteLine(doc); Console.Read();

        } 
    } 
}

无论是增删改查,我觉得思路都差不多一样,首先我们要从XML文档里面理解它们之间的层级关系,之所以要理解,是因为我们的操作都是需要通过定位来进行相应的操作。比方说要操作元素的话,我们要弄清这个元素怎么才能被定位到,然后再考虑我们下面要进行的操作。本文从基础的层面上介绍了Linq To XML的一般操作方法,希望浅薄的理解能引起大家少少的共鸣!如果你也喜欢此文的话,请保留本文的链接

 
posted @ 2011-11-25 08:28  csdbfans  阅读(1372)  评论(4编辑  收藏  举报