Accessing Data with Microsoft .NET Framework 4: LINQ to XML

  • 6/15/2011

Lesson 3: Transforming XML Using LINQ to XML

In addition to performing LINQ queries, another benefit of LINQ to XML is the ability to perform transformations. Prior to LINQ to XML, the best way to transform XML was to use XSLT, but you will certainly find that LINQ to XML is much easier to use than XSLT.

What can you transform XML to? You can transform it to a different form of XML, or to text, or to HTML, or to objects. Best of all is that you have complete control using Visual Basic or C#.

Transforming XML to Objects

To transform XML to objects, you simply use all the techniques described in this chapter to load and query the XML and the techniques described in Chapter 3 to convert to objects.

The code sample that follows uses a Customer class and an Order class. These classes are defined as follows:

Sample of Visual Basic Code

Public Class Customer
   Public Property Id() As String
   Public Property Name() As String
   Public Property Orders() As List(Of Order)
End Class

Public Class Order
   Public Property Id() As Integer
   Public Property Freight() As Decimal
End Class

Sample of C# Code

public class Customer
{
   public string Id { get; set; }
   public string Name { get; set; }
   public List<Order> Orders { get; set; }
}

public class Order
{
   public int Id { get; set; }
   public decimal Freight { get; set; }
}

In the following code sample, an XML document is loaded into an XDocument object from the XDocumentTest.xml file that was saved in the previous lesson examples. This XML document contains a list of customers with their orders, and then a LINQ query is provided to create a generic IEnumerable of Customer, but, within the select statement, a nested LINQ query is populating the Orders property of each customer. Finally, the results are displayed.

Sample of Visual Basic Code

Private Sub TransformToObjectsToolStripMenuItem_Click( _
      ByVal sender As System.Object, ByVal e As System.EventArgs) _
      Handles TransformToObjectsToolStripMenuItem.Click
   Dim doc = XDocument.Load(getFilePath("XDocumentTest.xml"))

   Dim CustomersOrders = _
      From c In doc.Descendants("Customer")
      Select New Customer With
      {
         .Id = CType(c.Attribute("CustomerID"), String),
         .Name = CType(c.Attribute("CompanyName"), String),
         .Orders = (From o In c.Elements("Order")
            Select New Order With
            {
               .Id = CType(o.Attribute("OrderID"), Integer),
               .Freight = CType(o.Attribute("Freight"), Decimal)
            }).ToList()
      }

   txtLog.Clear()
   For Each c In CustomersOrders
      txtLog.AppendText( _
         String.Format("ID:{0} Name:{1}", c.Id, c.Name) + vbCrLf)
      For Each o In c.Orders
         txtLog.AppendText( _
            String.Format("  OrderID:{0} Freight:{1,7:C}", _
                          o.Id, o.Freight) + vbCrLf)
      Next
   Next
End Sub

Sample of C# Code

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

Result

ID:ALFKI Name:Alfreds Futterkiste
   OrderID:10643 Freight: $29.46
   OrderID:10692 Freight: $61.02
   OrderID:10702 Freight: $23.94
   OrderID:10835 Freight: $69.53
   OrderID:10952 Freight: $40.42
   OrderID:11011 Freight:  $1.21
ID:ANATR Name:Ana Trujillo
   OrderID:10308 Freight:  $1.61
   OrderID:10625 Freight: $43.90
   OrderID:10759 Freight: $11.99
   OrderID:10926 Freight: $39.92
ID:ANTON Name:Antonio Moreno
   OrderID:10365 Freight: $22.00
   OrderID:10507 Freight: $47.45
   OrderID:10535 Freight: $15.64
   OrderID:10573 Freight: $84.84
   OrderID:10677 Freight:  $4.03
   OrderID:10682 Freight: $36.13
   OrderID:10856 Freight: $58.53
ID:AROUT Name:Around the Horn
   OrderID:10355 Freight: $41.95
   OrderID:10383 Freight: $34.24
   OrderID:10453 Freight: $25.36
   OrderID:10558 Freight: $72.97
   OrderID:10707 Freight: $21.74
   OrderID:10741 Freight: $10.96
   OrderID:10743 Freight: $23.72
   OrderID:10768 Freight:$146.32
   OrderID:10793 Freight:  $4.52
   OrderID:10864 Freight:  $3.04
   OrderID:10920 Freight: $29.61
   OrderID:10953 Freight: $23.72
   OrderID:11016 Freight: $33.80

The result shows that the transformation took place. In a real application, you would probably use the Customer and Order objects for a business purpose rather than simply to display them on the screen.

Transforming XML to Text

In the preceding code sample, if your only goal was to display the results, you could have simply converted the XML to a generic IEnumerable of String and then displayed the results. The following code sample demonstrates the use of LINQ to XML to convert XML to text.

Sample of Visual Basic Code

   Private Sub TransformToTextToolStripMenuItem_Click( _
         ByVal sender As System.Object, ByVal e As System.EventArgs) _
         Handles TransformToTextToolStripMenuItem.Click
      Dim doc = XDocument.Load(getFilePath("XDocumentTest.xml"))

      Dim CustomersOrders = _
         From c In doc.Descendants("Customer")
         Select New With
         {
            .CustomerInfo = _
               String.Format("ID:{0} Name:{1}" + vbCrLf, _
                              CType(c.Attribute("CustomerID"), String),
                              CType(c.Attribute("CompanyName"), String)
                              ),
            .OrderInfo = From o In c.Elements("Order")
                     Select String.Format(
                        "   OrderID:{0} Freight:{1,7:C}" + vbCrLf, _
                             CType(o.Attribute("OrderID"), Integer),
                           CType(o.Attribute("Freight"), Decimal))
         }

      txtLog.Clear()
      For Each c In CustomersOrders
         txtLog.AppendText(c.CustomerInfo)
         For Each o In c.OrderInfo
            txtLog.AppendText(o)
         Next
      Next
   End Sub

Sample of C# Code

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

This code sample produces the same results as the preceding one. The difference is that the string formatting is in the LINQ queries, and instead of creating a Customer and an Order class, an anonymous type holds the result as strings, so the nested loop displaying the result is much simpler.

Transforming XML to XML

You can use LINQ to XML to transform an XML document in one format into an XML document in a different format. Visual Basic really shines with its use of XML literals, to which you were introduced in Lesson 1. Visual Basic implementation of XML literals can simplify XML to XML transformations. C# users who want to use XML literals must learn Visual Basic, but don’t throw away your C# book. Instead, you can do all your XML literals in a separate Visual Basic DLL project and then set a reference to the DLL in your C# code.

In the following sample, the XML document that contains customers and their orders is transformed to an XML document that has the same information but is formatted differently.

Sample of Visual Basic Code

Private Sub TransformXMLToXMLToolStripMenuItem_Click( _
      ByVal sender As System.Object, ByVal e As System.EventArgs) _
      Handles TransformXMLToXMLToolStripMenuItem.Click
   Dim doc = XDocument.Load(getFilePath("XDocumentTest.xml"))
   Dim newXml = _
       <root>
          <%= From o In doc...<Order> _
             Select <Order CustID=<%= o.Parent.@CustomerID %>
                       CustName=<%= o.Parent.@CompanyName %>
                       OrdID=<%= o.@OrderID %>
                       OrdFreight=<%= o.@Freight %>/>
          %>
       </root>
   txtLog.Text = newXml.ToString()
End Sub

Sample of C# Code

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

Result

<root>
  <Order CustID="ALFKI" CustName="Alfreds Futterkiste" OrdID="10643"
OrdFreight="29.4600" />
  <Order CustID="ALFKI" CustName="Alfreds Futterkiste" OrdID="10692"
OrdFreight="61.0200" />
  <Order CustID="ALFKI" CustName="Alfreds Futterkiste" OrdID="10702"
OrdFreight="23.9400" />
  <Order CustID="ALFKI" CustName="Alfreds Futterkiste" OrdID="10835"
OrdFreight="69.5300" />
  <Order CustID="ALFKI" CustName="Alfreds Futterkiste" OrdID="10952"
OrdFreight="40.4200" />
  <Order CustID="ALFKI" CustName="Alfreds Futterkiste" OrdID="11011" OrdFreight="1.2100"
/>
  <Order CustID="ANATR" CustName="Ana Trujillo" OrdID="10308" OrdFreight="1.6100" />
  <Order CustID="ANATR" CustName="Ana Trujillo" OrdID="10625" OrdFreight="43.9000" />
  <Order CustID="ANATR" CustName="Ana Trujillo" OrdID="10759" OrdFreight="11.9900" />
  <Order CustID="ANATR" CustName="Ana Trujillo" OrdID="10926" OrdFreight="39.9200" />
  <Order CustID="ANTON" CustName="Antonio Moreno" OrdID="10365" OrdFreight="22.0000" />
  <Order CustID="ANTON" CustName="Antonio Moreno" OrdID="10507" OrdFreight="47.4500" />
  <Order CustID="ANTON" CustName="Antonio Moreno" OrdID="10535" OrdFreight="15.6400" />
  <Order CustID="ANTON" CustName="Antonio Moreno" OrdID="10573" OrdFreight="84.8400" />
  <Order CustID="ANTON" CustName="Antonio Moreno" OrdID="10677" OrdFreight="4.0300" />
  <Order CustID="ANTON" CustName="Antonio Moreno" OrdID="10682" OrdFreight="36.1300" />
  <Order CustID="ANTON" CustName="Antonio Moreno" OrdID="10856" OrdFreight="58.5300" />
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="10355" OrdFreight="41.9500" />
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="10383" OrdFreight="34.2400" />
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="10453" OrdFreight="25.3600" />
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="10558" OrdFreight="72.9700" />
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="10707" OrdFreight="21.7400" />
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="10741" OrdFreight="10.9600" />
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="10743" OrdFreight="23.7200" />
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="10768" OrdFreight="146.3200"
/>
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="10793" OrdFreight="4.5200" />
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="10864" OrdFreight="3.0400" />
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="10920" OrdFreight="29.6100" />
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="10953" OrdFreight="23.7200" />
  <Order CustID="AROUT" CustName="Around the Horn" OrdID="11016" OrdFreight="33.8000" />
</root>

Both of these language samples produce the same result, but the C# version looks more obfuscated than the Visual Basic example. XML literals enable the Visual Basic programmer to simply embed the elements as literals in the code and use <%= expression block %> syntax in the code. This is very similar to expression blocks in ASP or ASP.NET applications. When referencing XML axes for navigation, Visual Basic enables you to use three dots instead of typing Descendants. You can also use dot notation to access a child element. This example code uses the dot notation to access an attribute by prefixing the attribute name with the @ symbol.

Practice: Use LINQ to XML to Transform Data

In this practice, you transform an Orders.xml XML file, which contains order information, into a different format that management can use. Here is an example of what the file looks like:

Orders.xml File

<Orders>
  <Order OrderNumber="SO43659">
    <LineItem Line="1" PID="349" Qty="1" Price="2024.9940" Freight="50.6249" />
    <LineItem Line="2" PID="350" Qty="3" Price="2024.9940" Freight="151.8746" />
    <LineItem Line="3" PID="351" Qty="1" Price="2024.9940" Freight="50.6249" />
    <LineItem Line="4" PID="344" Qty="1" Price="2039.9940" Freight="50.9999" />
    <LineItem Line="5" PID="345" Qty="1" Price="2039.9940" Freight="50.9999" />
    <LineItem Line="6" PID="346" Qty="2" Price="2039.9940" Freight="101.9997" />
    <LineItem Line="7" PID="347" Qty="1" Price="2039.9940" Freight="50.9999" />
    <LineItem Line="8" PID="229" Qty="3" Price="28.8404" Freight="2.1630" />
    <LineItem Line="9" PID="235" Qty="1" Price="28.8404" Freight="0.7210" />
    <LineItem Line="10" PID="218" Qty="6" Price="5.7000" Freight="0.8550" />
    <LineItem Line="11" PID="223" Qty="2" Price="5.1865" Freight="0.2593" />
    <LineItem Line="12" PID="220" Qty="4" Price="20.1865" Freight="2.0187" />
  </Order>
  <Order OrderNumber="SO43660">
    <LineItem Line="1" PID="326" Qty="1" Price="419.4589" Freight="10.4865" />
    <LineItem Line="2" PID="319" Qty="1" Price="874.7940" Freight="21.8699" />
  </Order>
<!--Many more orders here -->
</Orders>

The resulting XML document is saved to a Results.xml file, and each Order element contains a TotalFreight attribute. The LineItem element is now called Item, the Line attribute is now called Number, the PID attribute is now called ID, and a LineTotal attribute has been added to each line item. The following is a sample of the Results.xml file.

Results.xml File

<ModifiedOrders>
  <Order OrderID="SO43659" TotalFreight="514.1408">
    <Item Number="1" ID="349" Price="2024.9940" Qty="1" LineTotal="2024.994" />
    <Item Number="2" ID="350" Price="2024.9940" Qty="3" LineTotal="6074.982" />
    <Item Number="3" ID="351" Price="2024.9940" Qty="1" LineTotal="2024.994" />
    <Item Number="4" ID="344" Price="2039.9940" Qty="1" LineTotal="2039.994" />
    <Item Number="5" ID="345" Price="2039.9940" Qty="1" LineTotal="2039.994" />
    <Item Number="6" ID="346" Price="2039.9940" Qty="2" LineTotal="4079.988" />
    <Item Number="7" ID="347" Price="2039.9940" Qty="1" LineTotal="2039.994" />
    <Item Number="8" ID="229" Price="28.8404" Qty="3" LineTotal="86.5212" />
    <Item Number="9" ID="235" Price="28.8404" Qty="1" LineTotal="28.8404" />
    <Item Number="10" ID="218" Price="5.7000" Qty="6" LineTotal="34.2" />
    <Item Number="11" ID="223" Price="5.1865" Qty="2" LineTotal="10.373" />
    <Item Number="12" ID="220" Price="20.1865" Qty="4" LineTotal="80.746" />
  </Order>
  <Order OrderID="SO43660" TotalFreight="32.3564">
    <Item Number="1" ID="326" Price="419.4589" Qty="1" LineTotal="419.4589" />
    <Item Number="2" ID="319" Price="874.7940" Qty="1" LineTotal="874.794" />
  </Order>
<!--Many more orders here -->
</ ModifiedOrders >

This project will be implemented as a simple Console application.

EXERCISE: Creating the Project and Implementing the Transformation

In this exercise, you create a Console Application project and then add code to the transformed XDocument class and save to the Result.xml file.

  1. In Visual Studio .NET 2010, choose File | New | Project.

  2. Select your desired programming language and then select the Console Application template. For the project name, enter OrderTransformer. Be sure to select a desired location for this project. For the solution name, enter OrderTransformerSolution. Be sure that Create Directory For Solution is selected and then click OK. After Visual Studio .NET finishes creating the project, Module1.vb (C# Program.cs) is displayed.

  3. In Main, declare a string for your file name and assign Orders.xml to it. Add code to the bottom of Main to prompt the user to press Enter to end the application. Your code should look like the following:

    Sample of Visual Basic Code

    Module Module1
       Sub Main()
          Dim fileName = "Orders.xml"
    
          Console.Write("Press <Enter> to end")
          Console.ReadLine()
       End Sub
    End Module

    Sample of C# Code

    namespace OrderTransformer
    {
       class Program
       {
          static void Main(string[] args)
          {
             string fileName = "Orders.xml";
    
             Console.Write("Press <Enter> to end");
             Console.ReadLine();
          }
       }
    }
  4. Add the Orders.xml file to your project. Right-click the OrderTransformer node in Solution Explorer and choose Add | Existing Item. In the bottom right corner of the Add Existing Item dialog box, click the drop-down list and select All Files (*.*). Navigate to the Begin folder for this exercise and select Orders.xml. If you don’t see the Orders. xml file, check whether All Files (*.*) has been selected.

  5. In Solution Explorer, click the Orders.xml file you just added. In the Properties window, set the Copy to Output Directory property to Copy If Newer.

    Because this file will reside in the same folder as your application, you will be able to use the file name without specifying a path.

  6. In the Main method, add code to load the Orders.xml file into an XDocument object and assign this object to a doc variable. For C#, add using System.Xml.Linq; to the top of your file. Your code should look like the following:

    Sample of Visual Basic Code

    Module Module1
       Sub Main()
          Dim fileName = "Orders.xml"
          Dim doc = XDocument.Load(fileName)
    
          Console.Write("Press <Enter> to end")
          Console.ReadLine()
       End Sub
    End Module

    Sample of C# Code

    namespace OrderTransformer
    {
       class Program
       {
          static void Main(string[] args)
          {
             string fileName = "Orders.xml";
             var doc = XDocument.Load(fileName);
    
             Console.Write("Press <Enter> to end");
             Console.ReadLine();
          }
       }
    }
  7. Declare a result variable and assign your LINQ to XML transformation to it. You need to iterate the Order elements to complete the transformation. If you’re using Visual Basic, be sure to take advantage of XML literals. Your code should look like the following:

    Sample of Visual Basic Code

    Dim result = _
        <ModifiedOrders>
           <%= From o In doc...<Order> _
              Select <Order OrderID=<%= o.@OrderNumber %>
                        TotalFreight=<%= o.<LineItem>.Sum(
                               Function(li) CType(li.@Freight, Decimal)) %>>
                        <%= From li In o.<LineItem>
                           Select <Item Number=<%= li.@Line %>
                                     ID=<%= li.@PID %>
                                     Price=<%= li.@Price %>
                                     Qty=<%= li.@Qty %>
                                     LineTotal=<%= li.@Price * li.@Qty %>/>
                        %>
                     </Order>
           %>
        </ModifiedOrders>

    Sample of C# Code

    var result = new XElement("ModifiedOrders",
          from o in doc.Descendants("Order")
          select new XElement("Order",
          new XAttribute("OrderID", (string)o.Attribute("OrderNumber")),
          new XAttribute("TotalFreight",
             o.Elements("LineItem").Sum(li=>(decimal) li.Attribute("Freight"))),
                from li in o.Elements("LineItem")
                   select new  XElement("Item",
                      new XAttribute("Number",(int)li.Attribute("Line")),
                      new XAttribute("ID", (int)li.Attribute("PID")),
                      new XAttribute("Price",(decimal)li.Attribute("Price")),
                      new XAttribute("Qty", (int)li.Attribute("Qty")),
                      new XAttribute("LineTotal",
                         (decimal)li.Attribute("Price") *
                         (int)li.Attribute("Qty"))
                      )
                   )
          );
  8. Add code to save the result to a Results.xml file on your desktop or to a location of your choice. Add imports System.IO (C# using System.IO;) to the top of your file. The completed Main method should look like the following.

    Sample of Visual Basic Code

    Sub Main()
       Dim fileName = "Orders.xml"
       Dim doc = XDocument.Load(fileName)
    
       Dim result = _
           <ModifiedOrders>
              <%= From o In doc...<Order> _
                 Select <Order OrderID=<%= o.@OrderNumber %>
                           TotalFreight=<%= o.<LineItem>.Sum(
                                  Function(li) CType(li.@Freight, Decimal)) %>>
                           <%= From li In o.<LineItem>
                              Select <Item Number=<%= li.@Line %>
                                        ID=<%= li.@PID %>
                                        Price=<%= li.@Price %>
                                        Qty=<%= li.@Qty %>
                                        LineTotal=<%= li.@Price * li.@Qty %>/>
                           %>
                        </Order>
              %>
           </ModifiedOrders>
       result.Save(Path.Combine(Environment.GetFolderPath( _
                   Environment.SpecialFolder.Desktop), "Results.xml"))
       Console.Write("Press <Enter> to end")
       Console.ReadLine()
    End Sub

    Sample of C# Code

    static void Main(string[] args)
    {
       string fileName = "Orders.xml";
       var doc = XDocument.Load(fileName);
       var result = new XElement("ModifiedOrders",
             from o in doc.Descendants("Order")
             select new XElement("Order",
             new XAttribute("OrderID", (string)o.Attribute("OrderNumber")),
             new XAttribute("TotalFreight",
                o.Elements("LineItem").Sum(li=>(decimal) li.Attribute("Freight"))),
                   from li in o.Elements("LineItem")
                      select new  XElement("Item",
                         new XAttribute("Number",(int)li.Attribute("Line")),
                         new XAttribute("ID", (int)li.Attribute("PID")),
                         new XAttribute("Price",(decimal)li.Attribute("Price")),
                         new XAttribute("Qty", (int)li.Attribute("Qty")),
                         new XAttribute("LineTotal",
                            (decimal)li.Attribute("Price") *
                            (int)li.Attribute("Qty"))
                         )
                      )
             );
       result.Save(Path.Combine(Environment.GetFolderPath(
          Environment.SpecialFolder.Desktop), "Results.xml"));
    
       Console.Write("Press <Enter> to end");
       Console.ReadLine();
    }
  9. Run the application. You should see a message stating, “Press <Enter> to end.” Press Enter to end the application. After running the application, locate the Results.xml file and open it. Your file should look like the following:

    Results.xml

    <?xml version="1.0" encoding="utf-8"?>
    <ModifiedOrders>
      <Order OrderID="SO43659" TotalFreight="514.1408">
        <Item Number="1" ID="349" Price="2024.9940" Qty="1" LineTotal="2024.9940" />
        <Item Number="2" ID="350" Price="2024.9940" Qty="3" LineTotal="6074.9820" />
        <Item Number="3" ID="351" Price="2024.9940" Qty="1" LineTotal="2024.9940" />
        <Item Number="4" ID="344" Price="2039.9940" Qty="1" LineTotal="2039.9940" />
        <Item Number="5" ID="345" Price="2039.9940" Qty="1" LineTotal="2039.9940" />
        <Item Number="6" ID="346" Price="2039.9940" Qty="2" LineTotal="4079.9880" />
        <Item Number="7" ID="347" Price="2039.9940" Qty="1" LineTotal="2039.9940" />
        <Item Number="8" ID="229" Price="28.8404" Qty="3" LineTotal="86.5212" />
        <Item Number="9" ID="235" Price="28.8404" Qty="1" LineTotal="28.8404" />
        <Item Number="10" ID="218" Price="5.7000" Qty="6" LineTotal="34.2000" />
        <Item Number="11" ID="223" Price="5.1865" Qty="2" LineTotal="10.3730" />
        <Item Number="12" ID="220" Price="20.1865" Qty="4" LineTotal="80.7460" />
      </Order>
      <Order OrderID="SO43660" TotalFreight="32.3564">
        <Item Number="1" ID="326" Price="419.4589" Qty="1" LineTotal="419.4589" />
        <Item Number="2" ID="319" Price="874.7940" Qty="1" LineTotal="874.7940" />
      </Order>
    <!-- more orders here-->
    </ModifiedOrders>

Lesson Summary

This lesson provided detailed information about transforming data by using LINQ to XML.

  • You can take advantage of LINQ projections to convert XML to objects.

  • LINQ projections can also help convert XML to a generic IEnumerable of string.

  • LINQ projections can also be used with the XDocument classes to convert XML to a different form of XML.

  • If you use Visual Basic, you can take advantage of XML literals to simplify transformations.

Lesson Review

You can use the following questions to test your knowledge of the information in Lesson 3, “Transforming XML Using LINQ to XML”. The questions are also available on the companion CD if you prefer to review them in electronic form.

  1. You have an XML file you want to transform to a different form of XML, and you want to use XML literals to simplify the transformation. Which language will you use?

    1. C#

    2. Visual Basic

    3. Either