LINQ to XML

一. 使用XDocument类:

1. 执行LINQ to XML查询:
XDocument类可以很简单地使用构造器构造,或使用Load或Parse方法来初始对象。下面的代码教你如何使用Parse方法来将XML字符串装载到XDocument对象中。然后将XML文档保存到XDocumentTest.xml文件中去。

      private void parseXDocumentToolStripMenuItem_Click(
         object sender, EventArgs e)
      {
         string xml = @"
            <CustomersOrders>
               <Customer CustomerID='ALFKI' CompanyName='Alfreds Futterkiste'>
                  <Order OrderID='10643' Freight='29.4600' />
                  <Order OrderID='10692' Freight='61.0200' />
                  <Order OrderID='10702' Freight='23.9400' />
                  <Order OrderID='10835' Freight='69.5300' />
                  <Order OrderID='10952' Freight='40.4200' />
                  <Order OrderID='11011' Freight='1.2100' />
               </Customer>
               <Customer CustomerID='ANATR' CompanyName='Ana Trujillo'>
                  <Order OrderID='10308' Freight='1.6100' />
                  <Order OrderID='10625' Freight='43.9000' />
                  <Order OrderID='10759' Freight='11.9900' />
                  <Order OrderID='10926' Freight='39.9200' />
               </Customer>
               <Customer CustomerID='ANTON' CompanyName='Antonio Moreno'>
                  <Order OrderID='10365' Freight='22.0000' />
                  <Order OrderID='10507' Freight='47.4500' />
                  <Order OrderID='10535' Freight='15.6400' />
                  <Order OrderID='10573' Freight='84.8400' />
                  <Order OrderID='10677' Freight='4.0300' />
                  <Order OrderID='10682' Freight='36.1300' />
                  <Order OrderID='10856' Freight='58.4300' />
               </Customer>
               <Customer CustomerID='AROUT' CompanyName='Around the Horn'>
                  <Order OrderID='10355' Freight='41.9500' />
                  <Order OrderID='10383' Freight='34.2400' />
                  <Order OrderID='10453' Freight='25.3600' />
                  <Order OrderID='10558' Freight='72.9700' />
                  <Order OrderID='10707' Freight='21.7400' />
                  <Order OrderID='10741' Freight='10.9600' />
                  <Order OrderID='10743' Freight='23.7200' />
                  <Order OrderID='10768' Freight='146.3200' />
                  <Order OrderID='10793' Freight='4.5200' />
                  <Order OrderID='10864' Freight='3.0400' />
                  <Order OrderID='10920' Freight='29.6100' />
                  <Order OrderID='10953' Freight='23.7200' />
                  <Order OrderID='11016' Freight='33.8000' />
               </Customer>
            </CustomersOrders>
         ";
         var doc = XDocument.Parse(xml);
         doc.Save(getFilePath("XDocumentTest.xml"));
         MessageBox.Show("XDocument Saved");
      }

下面的这段代码使用Load方法来初始XDocument对象。XML的内容还是与前面的例子一样。我们要查找出order ID 10677的customer ID和它的freight。

      private void lINQQueryToolStripMenuItem_Click(
         object sender, EventArgs e)
      {
         var doc = XDocument.Load(getFilePath("XDocumentTest.xml"));
         var result = (from order in doc.Descendants("Order")
                       where order.Attribute("OrderID").Value == "10677"
                       select new
                                {
                                   OrderID = (int)order.Attribute("OrderID"),
                                   CustomerID = (string)order.Parent.Attribute("CustomerID"),
                                   Freight = (decimal)order.Attribute("Freight")
                                }).FirstOrDefault();
         txtLog.Text = string.Format("OrderID:{0}  CustomerID:{1}  Freight:{2:C}",
            result.OrderID, result.CustomerID, result.Freight);
      }

2.使用LINQ to XML聚合运算(Aggregate):
如果你想查询每个客户的freight的总和,你可以向下面的代码这样使用LINQ to XML。

      private void lINQQuerySumToolStripMenuItem_Click(
         object sender, EventArgs e)
      {
         var doc = XDocument.Load(getFilePath("XDocumentTest.xml"));
         var result = from customer in doc.Descendants("Customer")
                      select new
                      {
                         CustomerID = (string)customer.Attribute("CustomerID"),
                         TotalFreight = customer.Descendants("Order")
                            .Sum(o => (decimal)o.Attribute("Freight"))
                      };
         txtLog.Clear();
         foreach (var customer in result)
         {
            txtLog.AppendText(string.Format("CustomerID:{0}  TotalFreight:{1,8:C}\r\n",
               customer.CustomerID, customer.TotalFreight));
         }
      }

3.使用LINQ to XML Join:
Join可以用在LINQ to XML和其他的LINQ providers,比如说LINQ to Objects。下面的代码展示了如何将一个数组和一个XML文件Join起来。

      private void lINQQueryJoinToolStripMenuItem_Click(
         object sender, EventArgs e)
      {
         string[] orders = { "10707", "10835", "10953" };

         var doc = XDocument.Load(getFilePath("XDocumentTest.xml"));
         var result = from order in doc.Descendants("Order")
                      join selected in orders
                         on (string)order.Attribute("OrderID") equals selected
                      select new
                   {
                      OrderID = (int)order.Attribute("OrderID"),
                      CustomerID = (string)order.Parent.Attribute("CustomerID"),
                      Freight = (decimal)order.Attribute("Freight")
                   };
         txtLog.Clear();
         foreach (var order in result)
         {
            txtLog.AppendText(
               string.Format("OrderID:{0}  CustomerID:{1}  Freight:{2:C}\r\n",
                           order.OrderID, order.CustomerID, order.Freight));
         }
      }

4.使用LINQ to XML 命名空间:
LINQ to XML支持使用命名空间。就象.NET框架命名空间一样,XML命名空间也是为了避免命名冲突,尤其是当将多个XML文档合并的时候,很有可能有同样名字的结点代表着不同的含义。比如说,一个Title元素在对一本书而言和对一个人而言的时候,含义是不同的。下面的这段代码演示了如何使用处理一个包含命名空间的XML文档。

      private void lINQQueryNamespaceToolStripMenuItem_Click(
         object sender, EventArgs e)
      {
         var xml =
            @"<Root xmlns:aw='http://www.adventure-works.com'
               xmlns='http://www.xyz.com'>
               <Child>1</Child>
               <aw:Child>2</aw:Child>
               <Child>3</Child>
               <aw:Child>4</aw:Child>
               <Child>5</Child>
               <aw:Child>6</aw:Child>
         </Root>";

         var doc = XDocument.Parse(xml);
         txtLog.Clear();

         var result1 = from c in doc.Descendants("Child")
                       select c;
         txtLog.AppendText("Query for Child\r\n");
         foreach (var xElement in result1)
         {
            txtLog.AppendText((string)xElement + "\r\n");
         }

         var aw = XNamespace.Get("http://www.adventure-works.com");
         var result2 = from c in doc.Descendants(aw + "Child")
                       select c;
         txtLog.AppendText("Query for aw+Child\r\n");
         foreach (var xElement in result2)
         {
            txtLog.AppendText((string)xElement + "\r\n");
         }

         var defaultns = XNamespace.Get("http://www.xyz.com");
         var result3 = from c in doc.Descendants(defaultns + "Child")
                       select c;
         txtLog.AppendText("Query for defaultns+Child\r\n");
         foreach (var xElement in result3)
         {
            txtLog.AppendText((string)xElement + "\r\n");
         }

         txtLog.AppendText("Done\r\n");
      }

二.使用LINQ to XML 对XML进行变换:

1. 将XML变换为Object:
下面的例子将XML变换为IEnumerable<Customer>和IEnumerable<Order>。

      private void transformToObjectsToolStripMenuItem_Click(
         object sender, EventArgs e)
      {
         var doc = XDocument.Load(getFilePath("XDocumentTest.xml"));


         var customersOrders =
            from c in doc.Descendants("Customer")
            select new Customer
               {
                  Id = (string)c.Attribute("CustomerID"),
                  Name = (string)c.Attribute("CompanyName"),
                  Orders = (from o in c.Elements("Order")
                            select new Order
                               {
                                  Id = (int)o.Attribute("OrderID"),
                                  Freight = (decimal)o.Attribute("Freight")
                               }).ToList()
               };

         txtLog.Clear();
         foreach (var c in customersOrders)
         {
            txtLog.AppendText(
               String.Format("ID:{0} Name:{1}\r\n", c.Id, c.Name));
            foreach (var o in c.Orders)
            {
               txtLog.AppendText(
                  String.Format("   OrderID:{0} Freight:{1,7:C}\r\n",
                                 o.Id, o.Freight));
            }
         }
      }


2. 将XML变换为Text:

下面的例子将XML变换为IEnumerable<String>。

      private void transformToTextToolStripMenuItem_Click(
         object sender, EventArgs e)
      {
         var doc = XDocument.Load(getFilePath("XDocumentTest.xml"));
         var customersOrders =
            from c in doc.Descendants("Customer")
            select new
            {
               CustomerInfo = string.Format(
                  "ID:{0} Name:{1}\r\n",
                  c.Attribute("CustomerID"),
                  c.Attribute("Name")),
               OrderInfo = from o in c.Elements("Order")
                           select string.Format(
                              "   OrderID:{0} Freight:{1,7:C}\r\n",
                              (int)o.Attribute("OrderID"),
                              (decimal)o.Attribute("Freight"))
            };
         foreach (var c in customersOrders)
         {
            txtLog.AppendText(c.CustomerInfo);
            foreach (var o in c.OrderInfo)
            {
               txtLog.AppendText(o);
            }
         }
      }


3. 将XML变换为其他XML:
你也可以使用LINQ to XML来将一个XML变换为另一种格式的XML文档。如果你使用Visual Basic的XML literals的话,将非常的简便。不过下面的例子还是使用C#来演示是如何将一个XML变换为其他格式的XML的。

      private void transformXMLToXMLToolStripMenuItem_Click(
         object sender, EventArgs e)
      {
         var doc = XDocument.Load(getFilePath("XDocumentTest.xml"));
         var newXml = new XDocument(
            new XElement("root",
               from o in doc.Descendants("Order")
               select new XElement("Order",
                  new XAttribute("CustID", o.Parent.Attribute("CustomerID").Value),
                  new XAttribute("CustName", o.Parent.Attribute("CompanyName").Value),
                  new XAttribute("OrdID", o.Attribute("OrderID").Value),
                  new XAttribute("OrdFreight", o.Attribute("Freight").Value)
                  )
               )
            );
         txtLog.Text = newXml.ToString();
      }

三. 小结:

1. XDocument提供了对XML文档in-memory,随机的读和写操作。
2. XDocument使用LINQ to XML来读取XML结点。
3. 当使用XAttribute对象时,你可以使用CType(C#显式转换 explicit cast)语句来把属性值转换为你想要的类型。
4. 当使用XElement对象时,你可以使用CType(C#显式转换 explicit cast)语句来把属性值转换为你想要的类型。
5. XDocument和XElement都提供了一个Load方法来从一个XmlReader文件进行装载。
6. XDocument和XElement都提供了构造器。你可以把代表XML内容的XNode传递给构造器进行构造。
7. XDocument和XElement都提供了一个Parse方法。你可以把XML字符串传递进来。
8. 你可以通过LINQ投射(projection)来将XML变换为Object。
9. LINQ投射可以将XML变换为IEnumerable<String>。
10. LINQ投射可以将XML变换为其他格式的XML。
11. 如果你使用Visual Basic,你可以使用XML literals来简化变化过程。

原文出自《Access Data with Microsoft .NET Framework 4》

你可能感兴趣的:(LINQ)