XDocument(转)

   XDocument 是管理内存中 XML 所有功能的模型!与 XmlDocument 和 XPathNavigator 不同,它擅长构建 XML 内容。XmlDocument 使 XML 构建不必太复杂,而 XPathNavigator 则完全不支持。

       如果要以非线性的方式生成 XML ,例如需要把一系列元素写入根元素,然后又要在这些元素里添加更多的信息,就必须使用 XDocument 这样的内存类。

       与 XmlDocument 非常相似,但有一个区别,在 LINQ to XML 模型里,特性没有被看做单独的节点而是被看做附加到其他元素的 名称/值 对。

       从技术层面而言,XDocument 是 LINQ 的一部分。它在 System.Xml.Linq 命名空间里,并且它是 .NET 3.5 中 System.Xml.Linq 程序集的一部分,使用这个类需要添加对该程序集的引用。

 

1. 使用 XDocument 创建 XML

       通过 XDocument 可以使用整洁和精确的代码生成 XML 内容,用 XElement 类还可以创建一个不表示完整的 XML 内容。

       所有的 LINQ to XML 类都提供了有用的构造函数,它允许在同一步里对其创建和初始化:

XElement element = new XElement("Price", "23.99");

 

       保存的代码甚至变得更加疯狂,它们能够在一行代码里创建嵌套的节点树。这两个类(XDocument、XElement)包含最后一个接收参数数组(params)的构造函数。这个参数数组包含一套嵌套的节点。

       下面的示例创建一个有两个嵌入元素以及它们内容的元素:

XElement element = new XElement("Starring",
        new XElement("Star", "Tom Hanks"),
        new XElement("Star", "Robin Wright")
);

 

       扩展上述的技术,我们创建一个完整的 XML 文档,包括全部的元素、文本内容、特性、注释:

private void WriteXmlWithXDocument()
{
    XDocument doc = new XDocument(
        new XDeclaration("1.0", "utf-8", "yes"),
        new XComment("Created: " + DateTime.Now.ToString()),
        new XElement("DvdList",
            new XElement("DVD",
                new XAttribute("ID", "1"),
                new XAttribute("Category", "Science Fiction"),
                new XElement("Title", "The Matrix"),
                new XElement("Director", "Larry Wachowski"),
                new XElement("Price", "18.74"),
                new XElement("Starring",
                    new XElement("Star", "Keanu Reeves"),
                    new XElement("Star", "Laurence Fishburne")
                )
            ),
 
            new XElement("DVD",
                new XAttribute("ID", "2"),
                new XAttribute("Category", "Drama"),
                new XElement("Title", "Forrest Gump"),
                new XElement("Director", "Robert Zemeckis"),
                new XElement("Price", "23.99"),
                new XElement("Starring",
                    new XElement("Star", "Tom Hanks"),
                    new XElement("Star", "Robin Wright")
                )
            ),
 
            new XElement("DVD",
                new XAttribute("ID", "3"),
                new XAttribute("Category", "Horror"),
                new XElement("Title", "The Others"),
                new XElement("Director", "Alejandro Amenábar"),
                new XElement("Price", "22.49"),
                new XElement("Starring",
                    new XElement("Star", "Nicole Kidman"),
                    new XElement("Star", "Cristopher Eccleston")
                )
            ),
 
            new XElement("DVD",
                new XAttribute("ID", "4"),
                new XAttribute("Category", "Mystery"),
                new XElement("Title", "Mulholland Drive"),
                new XElement("Director", "David Lynch"),
                new XElement("Price", "25.74"),
                new XElement("Starring",
                    new XElement("Star", "Laura Harring")
                )
            ),
 
            new XElement("DVD",
                new XAttribute("ID", "5"),
                new XAttribute("Category", "Science Fiction"),
                new XElement("Title", "A.I. Artificial Intelligence"),
                new XElement("Director", "Steven Spielberg"),
                new XElement("Price", "23.99"),
                new XElement("Starring",
                    new XElement("Star", "Haley Joel Osment"),
                    new XElement("Star", "Jude Law")
                )
            )
        )
    );
 
    doc.Save(Server.MapPath("DvdList.xml"));
}

这段代码的作用和以前介绍的 XmlTextWrite 代码的作用完全相同,但是它更短,更容易阅读。它也比创建内存中的 XmlDocument 的等效代码更简单!另外,这样书写的代码通过语句精确的缩进反映了 XML 元素的嵌套关系,这让你迅速知道 XML 文档的整体形状。

结论:

       创建 XML 文档的首选操作类就是 XDocument 。

 

2. 使用 XDocument 读取流

       XDocument 还可以简化对 XML 内容的读取和导航,得到一个含有内容的 XDocument 之后,可以使用 XElement 类的主要属性和方法深入节点树。

  • XDocument.Load():从文件、URI 或流中读取 XML 文档
  • XDocument.Parse():从一个字符串加载 XML 文档

XElement 类的核心方法:

Attributes() 获取这个元素的 Attribute 对象的集合
Attribute() 获取特定名称的 Attribute
Elements() 获取第一层的子 XElement 元素,或者你可以指定元素的名称。
Element() 获取由该元素包含的具有指定名称的 XElement ,如果没有匹配的就返回空值
Nodes() 获取该元素包含的所有 XNode 对象,这包括元素以及其他内容,如注释

       请注意 XDocument 和 XmlDocument 一个很重要的区别。XDocument 嵌套的元素通过方法而不是属性来暴露,这让你能够过滤出你感兴趣的那部分元素,当然,你也可以获取所有元素。

 

       XDocument 类(以及其他 LINQ to XML 类)通常提供更多的成员:

  • 节点成员(FirstNode、LastNode、NextNode、PreviousNode、Parent)
  • 检查是否有孩子(HasElements)、特性(HasAttributes)、内容(IsEmpty)
  • 插入、移除等其他操作( Add()、AddAfterSelf()AddBeforeSelf()、RemoveNodes()、Remove()、ReplaceWith()等)

       LINQ to XML 的另一个简化是它不要求你区分元素和其中的文本,它们在 XML DOM 里由两个单独的节点表示。你可以通过把他转换为相应的数据类型得到内部的值:

string title = (string)titleElement;
Decimal price = (Decimal)decimalElement;

       设置元素内的文本内容同样简单,只要把新值赋给 Value 属性:

priceElement = (decimal)priceElement * 2;

       下面这段直观的代码重写之前的 XPathNavigator 的 XML 处理代码。它扫描可用的元素,并把标题、导演以及价格信息添加到列表里:

private string ReadXML()
{
    string xmlFile = Server.MapPath("DvdList.xml");
    XDocument doc = XDocument.Load(xmlFile);
 
    StringBuilder str = new StringBuilder();
    foreach (XElement element in doc.Element("DvdList").Elements())
    {
        // element.Element("Title").ToString() 出来的格式是
        // <Title>......</Title>,因此取值只能使用下面的转换
        str.Append("<ul><b>");
        str.Append((string)element.Element("Title"));
        str.Append("</b><li>");
        str.Append((string)element.Element("Director"));
        str.Append("</li><li>");
        str.Append(string.Format("{0:C}", (decimal)element.Element("Price")));
        str.Append("</li></ul>");
    }
    return str.ToString();
}

 

3. 命名空间

       XDocument 类以特别优雅的方式处理命名空间。只要定义一个 XNameSpace 对象,然后使用它作为名称的一部分创建 XElement 元素即可:

XNamespace ns = "http://www.somecompany.com/DvdList";
XDocument doc = new XDocument(
    new XDeclaration("1.0", "utf-8", "yes"),
    new XComment("Created: " + DateTime.Now.ToString()),
    new XElement(ns + "DvdList",
        new XElement(ns + "DVD",
            new XAttribute("ID", "1"),
            new XAttribute("Category", "Science Fiction"),
            new XElement(ns + "Title", "The Matrix"),
            new XElement(ns + "Director", "Larry Wachowski"),
            new XElement(ns + "Price", "18.74"),
            new XElement(ns + "Starring",
                new XElement(ns + "Star", "Keanu Reeves"),
                new XElement(ns + "Star", "Laurence Fishburne")
            )
        )
    )
    ......
);

       所有元素被放到了新的 XML 命名空间,但特性没有,因为特性已经是附加到元素的了,所以没必要特别再把特性放到同一个命名空间里。

 

       如果元素在 XML 命名空间里,对 XML 文档进行遍历的时候必须同时考虑命名空间:

XNamespace ns = "http://www.somecompany.com/DvdList";
string title = (string)element.Element(ns + "Title");
posted @ 2013-12-05 13:29  邹邹  Views(1085)  Comments(0)    收藏  举报