The LINQ Contains method takes two parameters. The first parameter is the value that you wish to use to search in the XML elements, and the second is the IEqualityComparer instance to compare the values.
Scenario
I have a very simple scenario for my example. Here I have an XML doc with a list of books and especially an element named <ReleaseDate>. I wish to search for books that I have released in a specified month. The date format I chose is dd-mm-yyyy and has numeric values, separated by hyphen ( - ).
<?xml version="1.0"?> <Library> <List> <BookName>Computer Architecture</BookName> <Category>Computers</Category> <Price>125.60</Price> <ReleaseDate>02-10-2015</ReleaseDate> </List> <List> <BookName>Advanced Composite Materials</BookName> <Category>Science</Category> <Price>172.56</Price> <ReleaseDate>15-05-2015</ReleaseDate> </List> <List> <BookName>Asp.Net 4 Blue Book</BookName> <Category>Programming</Category> <Price>56.00</Price> <ReleaseDate>06-10-2015</ReleaseDate> </List> <List> <BookName>Stategies Unplugged</BookName> <Category>Science</Category> <Price>99.99</Price> <ReleaseDate>11-08-2015</ReleaseDate> </List> <List> <BookName>Teaching Science</BookName> <Category>Science</Category> <Price>164.10</Price> <ReleaseDate>02-10-2015</ReleaseDate> </List> <List> <BookName>Challenging Times</BookName> <Category>Business</Category> <Price>150.70</Price> <ReleaseDate>11-08-2015</ReleaseDate> </List> <List> <BookName>Circuit Bending</BookName> <Category>Science</Category> <Price>112.00</Price> <ReleaseDate>07-02-2015</ReleaseDate> </List> <List> <BookName>Popular Science</BookName> <Category>Science</Category> <Price>210.40</Price> <ReleaseDate>21-08-2015</ReleaseDate> </List> <List> <BookName>ADOBE Premiere</BookName> <Category>Computers</Category> <Price>62.20</Price> <ReleaseDate>01-10-2015</ReleaseDate> </List> </Library>
In the markup section, I have an HTML select option, which has values from 01 to 12, for months of the year. Two more controls, a button to call a code behind procedure to search for the selected pattern in XML and a label control to display the result.
<div style="font:13px Verdana;">
<%-- SEARCH A VALUE IN XML --%>
<div style="width:300px;border:solid 1px #CCC;padding:10px;">
<p>Select the Month:
<select id="selMonth" runat="server">
<option value="">-- SELECT --</option>
<option value="01">01</option>
<option value="02">02</option>
<option value="03">03</option>
<option value="04">04</option>
<option value="05">05</option>
<option value="06">06</option>
<option value="07">07</option>
<option value="08">08</option>
<option value="09">09</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
</select>
<button id="btSearch" onserverclick="search_text" runat="server">Search</button>
</p>
<p><label id="lblXML" runat="server"></label></p>
</div>
</div>
using System; using System.Collections.Generic; // FOR IEnumerable. using System.Linq; // FOR Descendants(). using System.Xml.Linq; // FOR XDocument, XElement. public partial class SiteMaster : System.Web.UI.MasterPage { protected void search_text(object sender, EventArgs e) { Search("-" + selMonth.Value + "-"); } private void Search(string sVal) { // LOAD XML DOCUMENT. var xml_Doc = XDocument.Load(Server.MapPath("library.xml")); IEnumerable<XElement> search_date = null; search_date = (from xFi in xml_Doc.Descendants("List") where xFi.Element("ReleaseDate").Value.Contains(sVal) select xFi ); // NOW DISPLAY THE VALUE. if ((search_date != null)) { lblXML.InnerHtml = ""; // CLEAR THE LABEL FOR NEW VALUES. foreach (XElement result in search_date) { lblXML.InnerHtml = lblXML.InnerHtml + "<b> Release Date: </b>" + result.Element("ReleaseDate").Value + "<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 /><br />"; } } else { lblXML.InnerHtml = "Found Nothing"; } } }
Option Explicit On Partial Class Site Inherits System.Web.UI.MasterPage Protected Sub search_text(ByVal sender As Object, ByVal e As EventArgs) Search("-" & Trim(selMonth.Value) & "-") End Sub Private Sub Search(ByVal sVal As String) ' LOAD XML DOCUMENT. Dim xml_Doc = XDocument.Load(Server.MapPath("library.xml")) Dim search_date As IEnumerable(Of XElement) search_date = (From xFi In xml_Doc.Descendants("List") _ Where xFi.Element("ReleaseDate").Value.Contains(sVal) ) ' NOW DISPLAY THE RESULT. If Not search_date Is Nothing Then lblXML.InnerHtml = "" For Each result As XElement In search_date lblXML.InnerHtml = lblXML.InnerHtml & _ "<b> Release Date: </b>" & result.Element("ReleaseDate").Value & "<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 /><br >" Next Else lblXML.InnerHtml = "Found Nothing" End If End Sub End Class
The Contains method will search for a specified pattern in the XML doc. It internally loops through each element and look for a match of a value that we have specified as its parameter.
where xFi.Element("ReleaseDate").Value.Contains(sVal)
LINQ Methods “toLower()” and “toUpper()”
The values that I am passing as parameter in the above example are numeric. However, if the values are alphabets, then remember, XML is case sensitive. For example, if you searching for a pattern in the <Category> element that has values are in UPPER case and you are passing a value in LOWER case, then convert the parameter to lower using .toLower() method.
<Category>PROGRAMMING</Category>
where xFi.Element("Category").Value.ToLower().Contains("programming")
Where xFi.Element("Category").Value.ToLower.Contains("programming")
Similarly, if it’s a reverse, that is, the values in XML in lower and the parameter is in upper case, then use .toUpper() method.