Reputation: 780
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
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
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
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