I have an XML document that contains a series of item nodes that look like this:
<data>
<item>
<label>XYZ</label>
<description>lorem ipsum</description>
<parameter type="id">123</parameter>
<parameter type="name">Adam Savage</parameter>
<parameter type="zip">90210</parameter>
</item>
</data>
and I want to LINQ it into an anonymous type like this:
var mydata =
(from root in document.Root.Elements("item")
select new {
label = (string)root.Element("label"),
description = (string)root.Element("description"),
id = ...,
name = ...,
zip = ...
});
What's the best way to pull each parameter type according to the value of its 'type' attribute? Since there are many parameter elements you wind up with root.Elements("parameter")
which is a collection. The best way I can think to do it is like this by method below but I feel like there must be a better way?
(from c in root.Descendants("parameter") where (string)c.Attribute("type") == "id"
select c.Value).SingleOrDefault()
You can use the XElement.
IEnumerable<T> can be used to query the XML data and for this standard query the operators show up as extension methods on any object that implements IEnumerable<T> and can be invoked like any other method.
The most important advantage of LINQ to XML is its integration with Language-Integrated Query (LINQ). This integration enables you to write queries on the in-memory XML document to retrieve collections of elements and attributes.
XDocument is from the LINQ to XML API, and XmlDocument is the standard DOM-style API for XML. If you know DOM well, and don't want to learn LINQ to XML, go with XmlDocument . If you're new to both, check out this page that compares the two, and pick which one you like the looks of better.
I would use the built-in query methods in LINQ to XML instead of XPath. Your query looks fine to me, except that:
Element
if you're looking for direct descendants of the item.Value
XElement
for a given type, instead of having several queries.Personally I don't think I'd even use a query expression for this. For example:
static XElement FindParameter(XElement element, string type)
{
return element.Elements("parameter")
.SingleOrDefault(p => (string) p.Attribute("type") == type);
}
Then:
var mydata = from item in document.Root.Elements("item")
select new {
Label = (string) item.Element("label"),
Description = (string) item.Element("description"),
Id = (int) FindParameter(item, "id"),
Name = (string) FindParameter(item, "name"),
Zip = (string) FindParameter(item, "zip")
};
I suspect you'll find that's neater than any alternative using XPath, assuming I've understood what you're trying to do.
use XPATH - it is very fast ( except xmlreader
- but a lot of if's)
using (var stream = new StringReader(xml))
{
XDocument xmlFile = XDocument.Load(stream);
var query = (IEnumerable)xmlFile.XPathEvaluate("/data/item/parameter[@type='id']");
foreach (var x in query.Cast<XElement>())
{
Console.WriteLine( x.Value );
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With