Angloos
Angloos

Reputation: 780

Linq for nested property

Below is my xml

<?xml version="1.0"?>
<Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <DataContainer xsi:type="ClassA">
    <Identifier></Identifier>
    <prop2></prop2>
    <prop3></prop3>
    <Key>549</Key>
  </DataContainer>
  <DataContainer xsi:type="ClassB">
    <Identifier></Identifier>
    <prop2></prop2>
    <prop3></prop3>
    <ClassC>
      <ClassD>
        <Identifier></Identifier>
        <prop2></prop2>
        <prop3></prop3>
        <Key>461</Key>
      </ClassD>
       <ClassD>
        <Identifier></Identifier>
        <prop2></prop2>
        <prop3></prop3>
        <Key>468</Key>
      </ClassD>
       <ClassD>
        <Identifier></Identifier>
        <prop2></prop2>
        <prop3></prop3>
        <Key>460</Key>
      </ClassD>
    </ClassC>
    <ClassE>
      <ClassF>
        <Identifier></Identifier>
        <prop2></prop2>
        <prop3></prop3>
        <Key>549</Key>
      </ClassF>
    </ClassE>
  </DataContainer>
..
..
..
.. Some more class that may or may not contain Key property
</Data>

I know its complicated xml structure but that how it is, sorry. I have to get the value of Identifier property based on Key property value, like where Key=549 or whatever. I Know i can do

Data.OfType<ClassA>().where(h=>h.Key==someValue).Select(...

But do i have to do this for each different class type as Key property is in different classes? Besides this, if in future another class came in and i have to find the identifier based on that class do i have to add another linq query to find that identifier? Is there any better solution for this or i am stuck with individual query for each class type?

I already have 'Data' deserialized object which Exactly looks like and Based upon above xml & i am looking for a way that gives me the 'identifier' property value based on Key..

Help will be appreciated,

Upvotes: 1

Views: 82

Answers (3)

goeldeepika3
goeldeepika3

Reputation: 91

To get all keyElements with closest Identifier value you can use the following: //Key allows to search for all keys in the XML & ../Identifier allows to find closest sibling to the key.

        var xDoc = XDocument.Load(@"C:\temp\test.xml");
        var keyElements = xDoc.XPathSelectElements("//Key").ToList();
        var items = new List<Tuple<string, string>>();
        foreach (var keyElement in keyElements)
        {
            var identifier = keyElement.XPathSelectElement("../Identifier");

            items.Add(new Tuple<string, string>(keyElement.Value, (identifier != null ? identifier.Value : null)));
        }

Upvotes: 0

CodingGorilla
CodingGorilla

Reputation: 19842

Based off of the comments from Rahul's answer, you might consider something like this:

public class DataBase
{
   public string Identifier { get; set; }
   public string Key { get; set; } 
}

public IEnumerable<DataBase> FindInstancesByKey(IEnumerable<DataBase> data, string key)
{
   return data.Where(d => d.Key == key);
}

public void Main()
{
   // Deserialize the data
   var data = Deserialize();

   var instances = FindInstancesByKey(data, "mykey");
   Console.WriteLine(instances.Select(x => x.Instance);
}

Creating a base class that all your XML instances inherit from gives you the strongly typed set up you need in order to start querying against the Instance and Key properties generically.

Upvotes: 0

Rahul Singh
Rahul Singh

Reputation: 21795

You can easily do it with Linq-to-XML like this:-

 XDocument xdoc = XDocument.Load("YourXML");
 IEnumerable<string> Identifiers = xdoc.Root.Elements("DataContainer")
                                       .Where(x => (string)x.Element("Key") == "549")
                                       .Select(x => (string)x.Element("Identifier"));

Upvotes: 3

Related Questions