c#操作Xml(四)

上集回顾

    上集初步介绍了Linq to Xml的基本操作,简单的新建xml操作和简单的查询xml操作。不过,可以注意到的是上集里面的xml都是没有Namespace的xml,那么有Namespace的xml如何操作哪?

设置目标

    先看看我们目标,完整这样一个xml:

<?xml version="1.0" encoding="utf-8" ?>

<v:persons xmlns:v="http://www.cnblogs.com/vwxyzh/">

  <v:person>

    <v:firstName>Zhenway</v:firstName>

    <v:lastName>Yan</v:lastName>

    <v:address>http://www.cnblogs.com/vwxyzh/</v:address>

  </v:person>

</v:persons>

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

    当然,这样的xml也有很多种等效写法,具体请参考w3shools

分析实现手段

    与之前一集相比,这里的”persons”,不再是一个纯粹的”persons”,而是一个带有Namespace的persons,所以在创建这样一个节点时不再是之前的:

var persons = new XElement("persons");

    而是需要修改成带有Namespace的节点名。

    那么如何获得这个带有Namespace的节点名哪?

    好吧,让我们回过头来看看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/vwxyzh/";

var persons = new XElement(v + "persons");

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

实现

    到这里,已经可以完成上面的那个目标xml了:

XNamespace v = "http://www.cnblogs.com/vwxyzh/";

XDocument doc = new XDocument(

    new XDeclaration("1.0", "utf-8", null),

    new XElement(v + "persons",

        new XElement(v + "person",

            new XElement(v + "firstName", "Zhenway"),

            new XElement(v + "lastName", "Yan"),

            new XElement(v + "address", "http://www.cnblogs.com/vwxyzh/")

            )

        )

    );

doc.Save(Console.Out);

    来看看执行结果:

<?xml version="1.0" encoding="gb2312"?>

<persons xmlns="http://www.cnblogs.com/vwxyzh/">

  <person>

    <firstName>Zhenway</firstName>

    <lastName>Yan</lastName>

    <address>http://www.cnblogs.com/vwxyzh/</address>

  </person>

</persons>

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

扩展

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

            XDocument doc = XDocument.Parse(@"<?xml version=""1.0"" encoding=""utf-8"" ?>

<v:persons xmlns:v=""http://www.cnblogs.com/vwxyzh/"">

  <v:person>

    <v:firstName>Zhenway</v:firstName>

    <v:lastName>Yan</v:lastName>

    <v:address>http://www.cnblogs.com/vwxyzh/</v:address>

  </v:person>

  <v:person>

    <v:firstName>Allen</v:firstName>

    <v:lastName>Lee</v:lastName>

    <v:address>http://www.cnblogs.com/allenlooplee/</v:address>

  </v:person>

</v:persons>");

            XNamespace v = "http://www.cnblogs.com/vwxyzh/";

            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);

            }

 

总结和下集预告

    Linq to Xml的介绍基本上就告一段落,不过,无论是Dom Api还是Linq to Xml都是In-Memory的工作方式,这样的工作方式对内存的要求相对较高,而且不适合超大xml文件的处理。

    因此,下集将介绍如何不占用内存的写一个超大的xml,当然其中也有Linq to Xml的一部分内容(Linq to Xml当初就预留了这部分)。

你可能感兴趣的:(xml)