Reputation: 185
I am using below query to return all the child elements and then based on child node i want to fetch the result.
XElement rootElement = XElement.Load(@"E:\Samples\TestConsole\TestConsoleApp\TestConsoleApp\XMLFile1.xml");
IEnumerable<XElement> lv1s = from lv1 in rootElement.Descendants("A")
where lv1.Attribute("Code").Value.Equals("A001") && lv1.Attribute("Lable").Value.Equals("A001")
select (from ltd in lv1.Descendants("A1")
where ltd.Attribute("Code").Value.Equals("001")
select ltd.Elements()).ToList();
But still i am having following error.
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<System.Collections.Generic.List<System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>>>' to 'System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>'. An explicit conversion exists (are you missing a cast?)
Please let me know.
i want my value of lv1s["A11"], lv1s["A22"]
below is my xml
<?xml version="1.0" encoding="utf-8" ?>
<Document>
<A Code="A001" Lable="A001">
<A1 Code="001">
<A11>A1</A11>
<A22>A2</A22>
<A33>A3</A33>
</A1>
</A>
<A Code="A002" Label="A002">
<A1 Code="002">
<A44>A44</A44>
<A55>A55</A55>
</A1>
</A>
</Document>
Please let me know.
Also How i can handle "Enumeration yielded no results" as count 0 in my return list since it's giving count>0 if this error occurs.
Upvotes: 4
Views: 10435
Reputation: 236328
Result of query has type IEnumerable<List<IEnumerable<XElement>>>
. But you are trying to assign it to IEnumerable<XElement>
. Why? Because for each A
element you are selecting list of A1
child elements. That gives you collection of lists.
You can use explicit result type to solve this issue. I.e. instead of IEnumerable<XElement> lv1s
use var lvls
. Or use actual lvls type: IEnumerable<List<IEnumerable<XElement>>> lvls
.
Or if you want to get IEnumerable<XElement>
then use SelectMany
:
IEnumerable<XElement> lv1s =
rootElement.Descendants("A")
.Where(lv1 => (string)lv1.Attribute("Code") == "A001" &&
(string)lv1.Attribute("Lable") == "A001")
.SelectMany(lv1 => lv1.Descendants("A1")
.Where(ltd => (string)ltd.Attribute("Code") == "001")
.Select(ltd => ltd.Elements());
Or rewrite your query this way:
IEnumerable<XElement> lv1s =
from lv1 in rootElement.Descendants("A")
where (string)lv1.Attribute("Code") == "A001" &&
(string)lv1.Attribute("Lable") == "A001"
from ltd in lv1.Descendants("A1")
where (string)ltd.Attribute("Code") == "001"
from e in ltd.Elements()
select e;
Returns following elements:
<A11>A1</A11>
<A22>A2</A22>
<A33>A3</A33>
Upvotes: 3
Reputation: 15375
A suggestion: Instead of using .Value
, cast as a string
. Also, if your variable is in any case an IEnumerable<XElement>
and not a List<XElement>
, why do you need ToList
?
XElement rootElement = XElement.Load(@"E:\Samples\TestConsole\TestConsoleApp\TestConsoleApp\XMLFile1.xml");
IEnumerable<XElement> lv1s =
from lv1 in rootElement.Descendants("A")
where (string)lv1.Attribute("Code") == "A001" && (string)lv1.Attribute("Lable") == "A001"
select (
from ltd in lv1.Descendants("A1")
where (string)ltd.Attribute("Code") == "001"
select ltd.Elements()
);
You have a nested LINQ query, and your query is also returning an IEnumerable<XElement>
. Try removing the nested query, and returning a single element as the result of the query (the parentheses are only added for clarity):
IEnumerable<XElement> lv1s = (
from lv1 in rootElement.Descendants("A")
where (string)lv1.Attribute("Code") == "A001" && (string)lv1.Attribute("Lable") == "A001"
from ltd in lv1.Descendants("A1")
where (string)ltd.Attribute("Code") == "001"
from e in ltd.Elements()
select e
);
Also, if you are only searching one level deep, you can use Elements
instead of Descendants
:
IEnumerable<XElement> lv1s = (
from lv1 in rootElement.Elements("A")
where (string)lv1.Attribute("Code") == "A001" && (string)lv1.Attribute("Lable") == "A001"
from ltd in lv1.Elements("A1")
where (string)ltd.Attribute("Code") == "001"
from e in ltd.Elements()
select e
);
And if all you want are the values of those elements -- A1
,A2
and A3
-- instead of XElement
objects:
IEnumerable<string> lv1s = (
from lv1 in rootElement.Elements("A")
where (string)lv1.Attribute("Code") == "A001" && (string)lv1.Attribute("Lable") == "A001"
from ltd in lv1.Elements("A1")
where (string)ltd.Attribute("Code") == "001"
from e in ltd.Elements()
select (string)e
);
Upvotes: 1