Reputation: 8351
I create a list of node object:
public class Node
{
public string Key { get; set; }
public string Value { get; set; }
}
public class ListNode : List<Node> { }
And i have an xml document :
<details>
<detail>
<node>
<key>xxx</key>
<value>111</value>
</node>
<node>
<key>yyy</key>
<value>222</value>
</node>
</detail>
<detail>
<node>
<key>zzz</key>
<value>333</value>
</node>
<node>
<key>aaa</key>
<value>444</value>
</node>
</detail>
</details>
what i want to do is to put these xml elements to a List of ListNode objects using linq to xml:
<node> => Node Object
<detail> => ListNode
<details> => List<ListNode>
this is my linq to xml request:
List<ListNode> listNodeDetails = xElement
.Element("details")
.Elements("detail")
.Elements("node")
.Select(n => new Node()
{ Key = n.Element("key").Value,
Value = n.Element("node").Element("value").Value
})
.ToList();
Upvotes: 1
Views: 3198
Reputation: 32266
First you don't really need the Node
or ListNode
classes. You should be able to get the same results using KeyValuePair<string,string>
(or Tuple<string,string>
) and List<KeyValuePari<string,string>>
(or List<Tuple<string,string>>
). Here's how you can get your desired results as a List<List<KeyValuePair>>
var results =
element.Elements("detail")
.Select(
x =>
x.Elements("node")
.Select(n => new KeyValuePair<string, string>(
n.Element("key").Value,
n.Element("value").Value))
.ToList())
.ToList();
The trick here is that you have an inner linq statement that builds up the List<KeyValuePair<string,string>>
while the outer linq statement builds that up into the List<List<KeyValuePair>>
. Also you have to use Elements
instead of Element
to get a colleciton of all the desired elements.
It's trivial to substitute in your Node
class (or Tuple<string,string>
). But it's a little more difficult, and unnecessary, to substitute in your ListNode
class.
However here is how you can get a List<ListNode>
as you currently have the ListNode
class defined.
List<ListNode> list = new List<ListNode>();
foreach (var detail in element.Elements("detail"))
{
var nodeList = new ListNode();
nodeList.AddRange(
detail.Elements("node")
.Select(
n => new Node
{
Key = n.Element("key").Value,
Value = n.Element("value").Value
}));
list.Add(nodeList);
}
Here you have to create a ListNode
before adding the nodes versus using the ToList
extension method. You could make that foreach
into a linq expression, but I typically avoid lambdas that have multiple statements whenever possible.
Upvotes: 3
Reputation: 86
You've not really said where you're stuck... Anyway, this should do the trick.
var xdoc = XDocument.Load("Test.xml");
var listNodeDetails = xdoc.Root
.Elements("detail")
.Elements("node").Select(
n => new Node
{
Key = n.Element("key").Value,
Value = n.Element("value").Value
}).ToList();
Upvotes: 1