I have a hard time time figuring out how to properly search an xml document. I have been reading the other forms like crazy today but just can't seem to understand it. Was hopeing someone could give me a little more detailed information on how to do this the correct way and why using LINQ. Here is the XML file.
<?xml version="1.0" encoding="utf-8"?>
<body>
<Customers>
<Client>
<Firstname Value="someguy" />
<LastName Value="test" />
<PhoneNumber Value="541555555" />
<Address Value="55 nowhere" />
<City Value="sometown" />
<State Value="somestate" />
</Client>
</Customers>
</body>
What I am tyring to accomplish is to return all of the values of each element that matches by a name of a customer. Here is my code.
IEnumerable<XElement> test = doc.Root.Descendants()
.Where(nodeName => nodeName.Name == "Client"
&& nodeName.Descendants().Any(x => x.Name == "Firstname"
&& x.Value == "someguy"));
foreach (XElement m in test)
{
MessageBox.Show(m.ToString());
}
Would really appreciate the help. Please also if possible explain what the idea of using LINQ is like the format if you will. Not really sure how to explain what I am asking but for the most part just more understanding of the way it works or format etc...
EDIT
I have tried the solution given and still nothing is seeming to work. Please show me what I am doing wrong here.
private void button2_Click(object sender, EventArgs e)
{
string seach = txtSearch.Text;
XDocument doc = XDocument.Load(@"C:\users\tim\desktop\test.xml");
var result = doc.Elements("Customers")
.Elements("Client")
.Where(x => x.Elements("Firstname")
.Where(c => c.Attribute("Value").Value == "someguy")
.Any())
.ToList();
foreach (var m in result)
{
MessageBox.Show(m.ToString());
}
}
EDIT:
Okay so I have gotten it to work now and output the data that I was looking for. Can someone please tell me if there is a more efficent way of doing what I have posted below this edit.
private void button2_Click(object sender, EventArgs e)
{
string seach = txtSearch.Text;
XDocument doc = XDocument.Load(@"C:\users\tim\desktop\test.xml");
var result = (from clientNode in doc.Root.Descendants("Client")
from name in clientNode.Descendants("Firstname")
where name.Attribute("Value").Value == "someguy"
select new
{
Fname = clientNode.Element("Firstname").Attribute("Value").Value,
Lname = clientNode.Element("LastName").Attribute("Value").Value,
Phone = clientNode.Element("PhoneNumber").Attribute("Value").Value,
Address = clientNode.Element("Address").Attribute("Value").Value,
City = clientNode.Element("City").Attribute("Value").Value,
State = clientNode.Element("State").Attribute("Value").Value
});
foreach (var m in result)
{
MessageBox.Show(m.Fname + "\n" +
m.Lname + "\n" +
m.Phone + "\n" +
m.Address + "\n" +
m.City + "\n" +
m.State);
}
You can use XElement
and search using a LINQ query like these:
XElement doc = XElement.Parse(xml);
var result = doc.Elements("Customers")
.Elements("Client")
.Where(x => x.Elements("Firstname")
.Where(c => c.Attribute("Value").Value == "someguy")
.Any())
.ToList();
So with input:
var xml =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<body>
<Customers>
<Client>
<Firstname Value=""someguy"" />
<LastName Value=""some last name"" />
<PhoneNumber Value=""123456"" />
<Address Value=""some where"" />
<City Value=""some town"" />
<State Value=""some state"" />
</Client>
<Client>
<Firstname Value=""someotherguy"" />
<LastName Value=""some other last name"" />
<PhoneNumber Value=""123456"" />
<Address Value=""some other where"" />
<City Value=""some other town"" />
<State Value=""some other state"" />
</Client>
</Customers>
</body>";
XElement doc = XElement.Parse(xml);
var result = doc.Elements("Customers")
.Elements("Client")
.Where(x => x.Elements("Firstname")
.Where(c => c.Attribute("Value").Value == "someguy")
.Any())
.ToList();
The result will be:
<Client>
<Firstname Value=""someguy"" />
<LastName Value=""some last name"" />
<PhoneNumber Value=""123456"" />
<Address Value=""some where"" />
<City Value=""some town"" />
<State Value=""some state"" />
</Client>
And you can show values for example:
MessageBox.Show(string.Format("Firstname: {0}\nLastName: {1}\nPhoneNumber: {2}\nAddress: {3}\nCity: {4}\nState: {5}",
result[0].Element("Firstname").Attribute("Value").Value,
result[0].Element("LastName").Attribute("Value").Value,
result[0].Element("PhoneNumber").Attribute("Value").Value,
result[0].Element("Address").Attribute("Value").Value,
result[0].Element("City").Attribute("Value").Value,
result[0].Element("State").Attribute("Value").Value));
Note:
FirstOrDefault()
instead of ToList()
;XElement.Load()
to load from file for example XElement doc = XElement.Load(@"d:\file.xml");
.Where(c => c.Name.ToString().ToLower() == "Customers".ToLower())
.Where(c => c.Attributes("Value").Where(a=>a.Value == "someguy").Any())
As an alternative to @Reza Aghaei's solution, XPath
is also a solution
var xml =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<body>
<Customers>
<Client>
<Firstname Value=""someguy"" />
<LastName Value=""some last name"" />
<PhoneNumber Value=""123456"" />
<Address Value=""some where"" />
<City Value=""some town"" />
<State Value=""some state"" />
</Client>
<Client>
<Firstname Value=""someotherguy"" />
<LastName Value=""some other last name"" />
<PhoneNumber Value=""123456"" />
<Address Value=""some other where"" />
<City Value=""some other town"" />
<State Value=""some other state"" />
</Client>
<Client>
<Firstname Value=""someguy"" />
<LastName Value=""some other last name"" />
<PhoneNumber Value=""12345634543"" />
<Address Value=""some other where"" />
<City Value=""some other town"" />
<State Value=""some other state"" />
</Client>
</Customers>
</body>";
XElement doc = XElement.Parse(xml);
foreach(var client in doc
.XPathSelectElements("./Customers/Client/Firstname[@Value='someguy']")
.Select(x => x.Parent))
Console.WriteLine (client);
If you prefer a Linq To Xml solution :
var results = (from c in doc.Descendants("Client")
from f in c.Descendants("Firstname")
where (string)f.Attribute("Value") == "someguy"
select c).ToList();
foreach(var r in results)
Console.WriteLine (r);
How to: Write Linq to Xml Queries with Complex Filtering
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With