Here's my XML File:
<Applications>
<Application Name="Abc">
<Section Name="xyz">
<Template Name="hello">
...
....
</Template>
</Section>
</Application>
<Application Name="Abc1">
<Section Name="xyz1">
<Template Name="hello">
...
....
</Template>
</Section>
</Application>
What I need to do is get the Template XElement from the given structure based upon the Name attribute of Template tag. The problem is there can be multiple template tags with same attribute Name. The Distinguishing factor is Application Name attribute value and section attribute value.
Currently I'm able to get the XElement by first getting Application Element based upon it's attribute, then Section based upon it's attribute and then finally template based upon it' name.
I wanted to know if there is a way to get it in one go.
I would use the fact that you can call Elements
or an existing sequence, so:
var template = doc.Descendants("Application")
.Where(x => (string) x.Attribute("Name") == applicationName)
.Elements("Section")
.Where(x => (string) x.Attribute("Name") == sectionName)
.Elements("Template")
.Where(x => (string) x.Attribute("Name") == templateName)
.FirstOrDefault();
You might even want to add an extension method somewhere:
public static IEnumerable<XElement> WithName(this IEnumerable<XElement> elements,
string name)
{
this elements.Where(x => (string) x.Attribute("Name") == name);
}
Then you can rewrite the query as:
var template = doc.Descendants("Application").WithName(applicationName)
.Elements("Section").WithName(sectionName)
.Elements("Template").WithName(templateName)
.FirstOrDefault();
... which I think you'll agree is quite readable :)
Note that the use of casting XAttribute
to string
instead of using the Value
property means that any elements without the Name
attribute are just effectively ignored rather than causing a NullReferenceException
.
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