2

I have a list of String

      List<String> lst=new List<String>{"A","B","C"}

And an xml file like

<Root>
<ChildList>
   <Childs>
      <Child Name="a1" Val="A"/>
      <Child Name="a2" val="A"/>
      <Child Name="b1" val="B"/>
   </Childs>
 </ChildList>
 </Root>

i need to read contets of the xml file and add to a dictionary

    Dictionary<String,List<String>> dict

where the dictionary key is the items in the "lst" and value is the attribute value of "Name" from the file

So the result will be like

   Key(String)            Value(List<String>)

   "A"                          "a1","a2"
   "B"                           "b1"
   "C"                           null

now i'm using nested for loop for this

Is there any wau to do this using LINQ to XML

Thanks in advance

0

2 Answers 2

3

I think this will do it:

XDocument doc = XDocument.Load("foo.xml");
ILookup<string, string> lookup = doc.Descendants("Childs")
                                    .First()
                                    .Elements("Child")
                                    .ToLookup(x => (string) x.Attribute("Val"),
                                              x => (string) x.Attribute("Name"));

var dictionary = lst.ToDictionary(x => x,
                         x => lookup[x].ToList().NullIfEmpty());

Using a helper method:

public static List<T> NullIfEmpty<T>(this List<T> list)
{
    return list.Count == 0 ? null : list;
}

If you don't mind having an empty list instead of null for items which aren't in the XML file, the second statement can be simplified, with no need for the helper method:

var dictionary = lst.ToDictionary(x => x, x => lookup[x].ToList());

Note that I've structured this so that it only needs to go through the XML file once, instead of searching through the file once for each element in the list.

Sign up to request clarification or add additional context in comments.

5 Comments

@Jon Skeet, I think the ToDictionary should be var dictionary = lookup.ToDictionary(x => x.Key, x => lookup[x.Key].ToList());.
@ Jon Skeet: Can you please explain the uses of ILookup
@Chris: No, because then you won't see entries in lst which aren't in the lookup. Also, in that case you'd just do ... = lookup.ToDictionary(x => x.Key, x => x.Value.ToList()); without looking the key up again.
@Pramodh: Basically it's like a dictionary, but where each key is associated with multiple values. Note that unlike a normal dictionary, if you ask for a key which doesn't exist in the lookup, it returns an empty sequence.
@Jon, ah sorry I missed that lst was from the code in the question.
1
var xml = @"<Root>
<ChildList>
   <Childs>
      <Child Name=""a1"" Val=""A""/>
      <Child Name=""a2"" Val=""A""/>
      <Child Name=""b1"" Val=""B""/>
   </Childs>
 </ChildList>
 </Root>";

var lst= new List<String> { "A", "B", "C" };
var doc = XDocument.Parse(xml);

var dict = (from item in lst
            select new
            {
                Key = item,
                Value = (from elem in doc.Root.Element("ChildList").Element("Childs").Elements("Child")
                         where (string)elem.Attribute("Val") == item
                         select (string)elem.Attribute("Name")).ToList()
            }).ToDictionary(i => i.Key, i => i.Value);

This can be made more efficient. I iterate over the elements once for every item in lst. I'll properly come up with another solution later if others don't come up with one.

1 Comment

@ lasseespeholt : Thank you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.