LINQtoXML

K

K Viltersten

I'm running the following code.

XElement r = XElement.Load("info.xml");
IEnumerable<XElement>
des = r.Descendants("A").Descendants("A1");

foreach (XElement d in des)
string v = d.Descendants("A1a")
.First<XElement>().Value;

I was expecting LINQ to give me more easy
access to the data structure. Perhaps
someone can suggest some changes.

1. Can i shorten the assignment to des
somehow? Something like "A.A1" would be
very helpful.

2. Why do i need to specify the type to
First() using <XElement>? Isn't it always
a XElement? How can i retrieve an int or
double instead of string?

3. Frankly, i was expecting LINQ to give
me a structure where intellisense would
let me "dot my way through" to the data
i need. Is that doable?

Also, after some reading, i'm still
unclear about the relation between
XElement and XNode (and the other X's as
well, but that's the two that _sound_
like a related leaf-node pair).

K Viltersten
 
J

Jon Skeet [C# MVP]

I'm running the following code.

XElement r = XElement.Load("info.xml");
IEnumerable<XElement>
des = r.Descendants("A").Descendants("A1");

foreach (XElement d in des)
string v = d.Descendants("A1a")
.First<XElement>().Value;

I was expecting LINQ to give me more easy
access to the data structure. Perhaps
someone can suggest some changes.

1. Can i shorten the assignment to des
somehow? Something like "A.A1" would be
very helpful.

You could use var :)

It sounds like you really want something XPath-like, in which case why
not use XPathSelectElements("A/A1")?
2. Why do i need to specify the type to
First() using <XElement>? Isn't it always
a XElement?

Yes, I'd expect so. What happens if you just call .First().Value? What
compiler error do you get?
How can i retrieve an int or double instead of string?

You'll need to use int.Parse etc. For XAttribute, there's an explicit
conversion which assumes the attribute value is in the appropriate XSD
format - I don't think there's anything similar for XElement.
3. Frankly, i was expecting LINQ to give
me a structure where intellisense would
let me "dot my way through" to the data
i need. Is that doable?

Given that the structure of your data depends on runtime information,
I don't see how that would be possible in a statically typed language.

It could be done in something like Boo, admittedly (with its bit of
duck typing).
Also, after some reading, i'm still
unclear about the relation between
XElement and XNode (and the other X's as
well, but that's the two that _sound_
like a related leaf-node pair).

XNode is just an (indirect) base class of XElement. (XElement derives
directly from XContainer, which derives directly from XNode.)

Jon
 
J

Jon Skeet [C# MVP]

You can cast XElement or XAttribute to double or int or other types:
double n = (double)d.Descendants("A1a").FirstOrDefault();

Doh! Thanks for the correction. I'd seen that the Value property was
just a string - didn't check for explicit casts.

<slaps forehead>

Jon
 
T

Tim Jarvis

K said:
I'm running the following code.

XElement r = XElement.Load("info.xml");
IEnumerable<XElement>
des = r.Descendants("A").Descendants("A1");

foreach (XElement d in des)
string v = d.Descendants("A1a")
.First<XElement>().Value;

I was expecting LINQ to give me more easy
access to the data structure. Perhaps
someone can suggest some changes.

if you only care about getting the Elements that you want at any depth
and don't need the Hierarchy context, then you can simply have done...

XElement info = XElement.Load("info.xml");
IEnumerable<int> A1IntValues = from x in info.DecendantsAndSelf("A1a")
Select (int)x;

I'm sure you would agree, that's pretty elegant.

Cheers Tim.

--
 
K

K Viltersten

I'm running the following code.
if you only care about getting the Elements that you want at any depth
and don't need the Hierarchy context, then you can simply have done...

XElement info = XElement.Load("info.xml");
IEnumerable<int> A1IntValues = from x in info.DecendantsAndSelf("A1a")
Select (int)x;

I'm sure you would agree, that's pretty elegant.


Yes, it is. However, i do care about the
hierarchy context in this case. Thanks,
everybody, for the answers!
 
T

Tim Jarvis

K said:
Yes, it is. However, i do care about the hierarchy context in this
case. Thanks, everybody, for the answers!

Ah ok, well you can still do this very elegantly with Linq, Linq allows
for subqueries, and for variable assignment within each loop, so
assuming a xml structure something like....

<Root>
<A Company="Microsoft">
<A1 Dept="Research and Development">
<A1a Name="Anders Hejlsberg" EmpNo="10"/>
<A1a Name="Don Box" EmpNo="15"/>
<A1a Name="Raymond Chen" EmpNo="5"/>
</A1>
<A1 Dept="Sales">
<A1a Name="Steve Balmer" EmpNo="3"/>
</A1>
</A>
<A Company="Quest Software">
<A1 Dept="Research and Development">
<A1a Name="Tim Jarvis" EmpNo="3501"/>
</A1>
<A1 Dept="Sales">
<A1a Name="John Doe" EmpNo="1"/>
</A1>
</A>
</Root>

You can wite a query like this....
XElement info = XElement.Load(@"C:\Temp\info.xml");
var report = from a in info.Descendants("A")
let Company = (string)a.Attribute("Company")
from a1 in a.Descendants("A1")
let Dept = (string)a1.Attribute("Dept")
from a1a in a1.Descendants("A1a")
let Name = (string)a1a.Attribute("Name")
let EmpID = (int)a1a.Attribute("EmpNo")
select new
{
Company = Company,
Dept = Dept,
Name = Name,
EmpID = EmpID
};

Very sexy, no?

Regards Tim.

--
 
Top