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 Sub
Its 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.