nav100
nav100

Reputation:

how to get root node attribute value using linq

I have the following XML. How to read the root node attribite value and it's decendents using LINQ? I am trying to read "dId" and "dTime" from root node, "id" from Customer element and Order number.

<?xml version="1.0" encoding="utf-8" ?>
 <Customers dId="wqwx" dTime="10-9-09 11:23">
   <Customer id="1">
      <Orders>
        <Order number="22" status="ok">
      </Orders>
   </Customer>
 </Customers>

I tried the following code but it doesn't work.

XDocument doc= XDocument.Load(@"C:\Customers.xml");
var q = from c in doc.Descendants("Customers")
        select new        
          {   
           dID = c.Attribute("dId"),
           dTime = c.Attribute("dTime");
          }

Upvotes: 3

Views: 5093

Answers (5)

praveen
praveen

Reputation: 1

It does not work the way you wrote it: while printing the above code would complain about anonymous type.

However, with this simple modified version d.Document.Root.Attribute("dId").Value; you can assign it to a string.

Upvotes: 0

Patrick Karcher
Patrick Karcher

Reputation: 23603

You have to end the order tag with: />

xDoc.Descendants("Customers") should work as well as xDoc.Elements("Customers").

Chris, is there a specific advantage to using .Elements?

Upvotes: 1

Laurel.Wu
Laurel.Wu

Reputation: 146

    XDocument d = XDocument.Parse(@"<?xml version='1.0' encoding='utf-8' ?>
        <Customers dId='wqwx' dTime='10-9-09 11:23'>
            <Customer id='1'>      
                <Orders>        
                    <Order number='22' status='ok'/>      
                </Orders>   
            </Customer> 
        </Customers>");
    var cu = d.Root.Elements().Where(n => n.Name == "Customer");


    var c = from cc in cu
            select new
            {
                dId = cc.Document.Root.Attribute("dId").Value,
                dTime = cc.Document.Root.Attribute("dTime").Value,
                ID = cc.Attribute("id").Value,
                number = cc.Element("Orders").Element("Order").Attribute("number").Value
            };

    foreach (var v in c)
    {
        Console.WriteLine("dId \t\t= {0}", v.dId);
        Console.WriteLine("dTime \t\t= {0}", v.dTime);
        Console.WriteLine("CustomerID \t= {0}", v.ID);
        Console.WriteLine("OrderCount \t= {0}", v.number);
    }

Console Output:
================================
dId = wqwx
dTime = 10-9-09 11:23
CustomerID = 1
OrderCount = 22
请按任意键继续. . .

Upvotes: 0

Muad&#39;Dib
Muad&#39;Dib

Reputation: 29196

first, fix your xml (<Order .... />) then, your linq should look like this....

// .Elements(...) selects all elements of type "Customer"
    var q = from c in xDoc.Elements("Customers") 
    select new
    {
        dID = c.Attribute("dId"), 
        dTime = c.Attribute("dTime")
    }; 

you should dl LinqPad... it lets you do Linq queries on the fly, even agains SQL databases. Then, once you get the results you want, copy and past your linq into your source code.

Upvotes: 1

Dabblernl
Dabblernl

Reputation: 16101

You can't use LINQ to access the root tag. The code below does what you want (I included a well formed xml file as well):

using System;
using System.Linq;
using System.Xml.Linq;

namespace ReadXmlSpike
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Reading file...");
            XDocument doc = XDocument.Load("Customers.xml");
            var customers =
                new
                    {
                        DID = (string) doc.Element("Customers").Attribute("did"),
                        DTime = (DateTime) doc.Element("Customers").Attribute("dTime"),
                        Customers = from customerxml in doc.Descendants("Customer")
                                    select
                                        new
                                            {
                                                ID = (string)customerxml.Attribute("id"),
                                                Orders = from orderxml in customerxml.Descendants("Order")
                                                         select
                                                             new
                                                                 {
                                                                     Number =(string) orderxml.Attribute("number")
                                                                 }
                                            }
                    };
            Console.WriteLine("Customersfile with id: {0} and time {1}",customers.DID,customers.DTime);
            foreach (var customer in customers.Customers)
            {
                Console.WriteLine("Customer with id {0} has the following orders:",customer.ID);
                foreach (var order in customer.Orders)
                {
                    Console.WriteLine("Order with number {0}",order.Number);
                }
            }
            Console.ReadLine();
        }
    }
}

and the xml file:

<?xml version="1.0" encoding="utf-8" ?>
<Customers did="www" dTime="10-09-09 11:23">
  <Customer id="1">
    <Orders>
      <Order number="22" status="ok"/>
      <Order number="23" status="bad"/>
    </Orders>
  </Customer>
  <Customer id="2">
    <Orders>
      <Order number="24" status="ok"/>
      <Order number="25" status="bad"/>
    </Orders>
  </Customer>
</Customers>

Upvotes: 0

Related Questions