Reputation: 9090
I'm trying to query a web.Config
file that contains WCF entries.
In the <service>
node there is a name attribute
that I am trying to match off of. So far my code has worked when doing the matching, but my issue is that it only returns 1 of the <endpoint>
nodes.
For example I could have this snippet of xml:
<service name="a">
<endpoint>1</endpoint>
<endpoint>2</endpoint>
<endpoint>3</endpoint>
</service>
<service name="b">
<endpoint>1</endpoint>
<endpoint>2</endpoint>
</service>
Everytime I get a match I want it to display all the <endpoint>
child nodes for that match.
This is the code I have so far:
IEnumerable<XElement> xmlURL =
from el in xmlFile.Root.Descendants("service")
where (string)el.Attribute("name") == serviceString
select el.Element("endpoint");
Console.WriteLine("Start: " + serviceString);
foreach (XElement el in xmlURL)
{
Console.WriteLine(el);
}
Console.WriteLine("End: " + serviceString + "\n\n");
Currently when it does the match only 1 endpoint is shown.
Upvotes: 2
Views: 19810
Reputation: 19872
I think you want this:
IEnumerable<XElement> xmlURL =
from el in xmlFile.Root.Descendants("service")
where (string)el.Attribute("name") == serviceString
select el.Descendants("endpoint");
Console.WriteLine("Start: " + serviceString);
foreach (XElement el in xmlURL)
{
Console.WriteLine(el);
}
Console.WriteLine("End: " + serviceString + "\n\n");
Notice I'm selecting el.Descendants()
rather than Element()
which will only ever return the first match (http://msdn.microsoft.com/en-us/library/system.xml.linq.xcontainer.element.aspx).
** UPDATE **
I think this is what you want, because you're only conerned with one specific match.
IEnumerable<XElement> xmlURL =
(from el in doc.Root.Descendants("service")
where el.Attribute("name").Value == serviceString
select el).First().Descendants();
So the result of the LINQ query is, as the compiler tells you, an IEnumerable of IEnumerables, so I take the First()
result of which gives me now an IEnumerable<XElement>
, and then we call Descendants()
on that, which gives you an IEnumerable of the endpoint XElement
's.
Also note here that I used the Value
property of the XAttribute
, you can't simply cast the XAttribute
to a string, you have to use that Value
property. I didn't catch that in my initial copy/paste answer.
** UPDATE 2 **
The above query can is probably a little easier to understand like this:
doc.Root.Descendants("service")
.Where(x => x.Attribute("name").Value == serviceString)
.First()
.Descendants();
** UPDATE 3 **
There is also the potential for a NRE on the attribute matching, so again this is probably an even better verison. =)
doc.Root.Descendants("service")
.Where(x => x.Attribute("name") != null && x.Attribute("name").Value == serviceString)
.First()
.Descendants();
Upvotes: 7