Scenario
I have data in an XML document and its big. I know the document has a list of books (an "inventory" of books) with important details about each book. I would like to use LINQ and its condition features, such as, the "where" clause, to filter XML elements based on a search value.
For example, I would enter the name of the book and I get the details about the book, instantly. For multiple results, I would enter a category (books category), such as, science and it would return all elements with the category science.
I have previously written an article, where I have explained with examples about how to load and read an XML document (all the elements and child elements, without filtering) using LINQ to XML. I am mentioning about the article, since I have borrowed few snippets from the examples, also the structure of the XML.
Here is the sample XML document.
Now, lets get on with this article.
I have divided this article into two sections. In the first section, I’ll show you how to set condition using where clause to filter a single XML element and read the values in it.
Second, using a similar principle, I’ll filter and read multiple XML elements by providing a value to the “where” clause and display the result. In the multiple selections, however, I have run a loop to read all the elements and its values.
* Single Conditional XML Element Selection in LINQ to XML
In the markup section, I have added few controls, such as, an <input> element of type text, to enter the search value and another <input> element of type button.
<div>
<p>
<label>Enter a value to search:</label>
<input type="text" id="tbBook" runat="server" />
</p>
<p>
<input type="button" id="bt" value="Search" runat="server"
onserverclick="find_my_book" />
</p>
<p><label id="lblXML" runat="server"></label></p>
</div>using System; using System.Collections.Generic; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Linq; // FOR Descendants(). using System.Xml.Linq; // FOR XDoument, XElement. public partial class SiteMaster : System.Web.UI.MasterPage { protected void find_my_book(object sender, EventArgs e) { lblXML.InnerHtml = ""; // CLEAR THE LABEL. // LOAD XML DOCUMENT. var xml_Doc = XDocument.Load(Server.MapPath("library.xml")); var sSearch_Value = tbBook.Value.ToString(); // SEARCH XML USING A CONDITION. XElement search_result = (from xFi in xml_Doc.Descendants("List") where xFi.Element("BookName").Value.ToUpper() == sSearch_Value.ToUpper() select xFi).FirstOrDefault(); if ((search_result != null)) { lblXML.InnerHtml = "<b> Name: </b>" + search_result.Element("BookName").Value + "<br />" + "<b> Category: </b> " + search_result.Element("Category").Value + "<br />" + "<b> Price: </b>" + search_result.Element("Price").Value; } else { lblXML.InnerHtml = "Found Nothing"; } } }
Option Explicit On
Partial Class Site
Inherits System.Web.UI.MasterPage
Protected Sub find_my_book(ByVal sender As Object, ByVal args As EventArgs)
lblXML.InnerHtml = "" ' CLEAR THE LABEL.
If Trim(tbBook.Value) <> "" Then
' LOAD XML DOCUMENT.
Dim xml_Doc = XDocument.Load(Server.MapPath("library.xml"))
Dim sSearch_Value As String = Trim(tbBook.Value)
' SEARCH XML USING A CONDITION.
Dim search_result As XElement = _
(From xFi In xml_Doc.Descendants("List") _
Where UCase(xFi.Element("BookName").Value) = UCase(sSearch_Value)
Select xFi).FirstOrDefault()
If Not search_result Is Nothing Then
lblXML.InnerHtml = _
"<b> Name: </b>" & search_result.Element("BookName").Value & "<br />" & _
"<b> Category: </b> " & search_result.Element("Category").Value & "<br />" & _
"<b> Price: </b>" & search_result.Element("Price").Value
Else
lblXML.InnerHtml = "Found Nothing"
End If
End If
End Sub
End Class* Multiple Conditional XML Element Selection in LINQ to XML
I am not repeating the markup for this example, as remains the same. Simply follow the code behind procedures.
protected void find_my_book(object sender, EventArgs e)
{
lblXML.InnerHtml = ""; // CLEAR THE LABEL.
// LOAD XML DOCUMENT.
var xml_Doc = XDocument.Load(Server.MapPath("library.xml"));
var sSearch_Value = tbBook.Value.ToString();
// SEARCH MULTIPLE XML ELEMENTS USING "where" CLAUSE.
IEnumerable<XElement> search_result = null;
search_result =
from xFi in xml_Doc.Descendants("List")
where xFi.Element("Category").Value.ToUpper() == sSearch_Value.ToUpper()
select xFi;
if ((search_result != null))
{
if (search_result.Count() > 0)
{
foreach (XElement result in search_result)
{
lblXML.InnerHtml = lblXML.InnerHtml + "<br />" +
"<b> Book Name: </b>" + result.Element("BookName").Value + "<br />" +
"<b> Category: </b> " + result.Element("Category").Value + "<br />" +
"<b> Price: </b>" + result.Element("Price").Value + "<br />";
}
}
else
{
lblXML.InnerHtml = "Found Nothing";
}
}
else
{
lblXML.InnerHtml = "Found Nothing";
}
}
Protected Sub find_my_book(ByVal sender As Object, ByVal args As EventArgs)
lblXML.InnerHtml = "" ' CLEAR THE LABEL.
If Trim(tbBook.Value) <> "" Then
' LOAD XML DOCUMENT.
Dim xml_Doc = XDocument.Load(Server.MapPath("library.xml"))
Dim sSearch_Value As String = Trim(tbBook.Value)
' SEARCH MULTIPLE XML ELEMENTS USING "where" CLAUSE.
Dim search_result As IEnumerable(Of XElement)
search_result = _
(From xFi In xml_Doc.Descendants("List") _
Where UCase(xFi.Element("Category").Value) = UCase(sSearch_Value)
Select xFi)
If Not search_result Is Nothing Then
If search_result.Count > 0 Then
For Each result As XElement In search_result
lblXML.InnerHtml = lblXML.InnerHtml & "<br />" & _
"<b> Book Name: </b>" & result.Element("BookName").Value & "<br />" & _
"<b> Category: </b> " & result.Element("Category").Value & "<br />" & _
"<b> Price: </b>" & result.Element("Price").Value & "<br />"
Next
Else
lblXML.InnerHtml = "Found Nothing"
End If
Else
lblXML.InnerHtml = "Found Nothing"
End If
End If
End SubIts an interesting piece of information and code. Let me explain what this article has for you. In the beginning, I have explained a small scenario and accordingly I have written codes to first filter a single XML element, by providing a value as condition in the “where” clause. Second, the code returns multiple XML elements, based on a certain condition.
I want you to notice, one important piece of method inside the code. I have used C# “toUpper()” method (UCase() method for Vb.Net). Please remember, that the values are case-sensitive.
