Aleks D Aleks D - 1 month ago 9
C# Question

XML data filtering and searching

I have the following chunk of XML code that I can easily generate.

<?xml version="1.0" encoding="utf-8"?>
<sessions>
<session date="14.10.2016" time="0:1" amount="1">
<Folder>C:\Users</Folder>
<Folder>C:\Tes2t</Folder>
<Folder>C:\Asgbsf\Aleksei</Folder>
</session>
<session date="14.10.2016" time="15:40" amount="7">
<Folder>C:\Users</Folder>
<Folder>C:\Tes2taaaa</Folder>
<Folder>C:\Asgbsf\Aleksei</Folder>
</session>
</sessions>


I am searching for data with attribute time 15:40 and date 14.10.2016 using following function

private static IEnumerable<XElement> FindElements(string filename, string date, string time)
{
XElement x = XElement.Load(filename);

return x.Descendants().Where(e => e.Attributes("date").Any(a => a.Value.Equals(date)) &&
e.Attributes("time").Any(a => a.Value.Equals(time)));
}


Function being executed like:

foreach (XElement x in FindElements(pathToXml, "14.10.2016", "15:40"))
Console.WriteLine(x.ToString());


Everything is fine, but the output is

<session date="14.10.2016" time="15:40" amount="7">
<Folder>C:\Users</Folder>
<Folder>C:\Tes2taaaa</Folder>
<Folder>C:\Asgbsf\Aleksei</Folder>
</session>


And I need just the folders, eg.

<Folder>C:\Users</Folder>
<Folder>C:\Tes2taaaa</Folder>
<Folder>C:\Asgbsf\Aleksei</Folder>


How do I achieve this? Help please.

Answer

You are currently returning the Element that has attribute of date and time with these values. What you should add to it is to return its child elements of Folder. You can do this by adding .Elements("Folder") after the .Where.

However, I think you can write your query a bit nicer:

Look for all the sessions that the values of those attriute equal to the given input. Then return the element.Elements("Folder").

I've added the .SelectMany() to flatten the inner list of child elements

string date = "14.10.2016";
string time = "15:40";

var result = (from element in XDocument.Load("data.xml").Descendants("session")
              where element.Attribute("date")?.Value == date &&
                    element.Attribute("time")?.Value == time
              select element.Elements("Folder")).SelectMany(item => item).ToList();