Reputation:
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
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
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
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
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
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