Use LINQ Contains Method to do SQL LIKE in C# to Search a Specified Pattern in XML

← PrevNext →

If you have worked with SQL Server, then I am sure you have used the SQL LIKE operator to fetch a specified pattern in your SQL table. The LIKE uses a “%” (percent) sign to fetch a pattern. However, if you are using XML as database and want to search for a pattern in it, then it’s different. I’ll show you how to do SQL LIKE on an XML using LINQ Contains method.

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 ( - ).

The XML
<?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>
The Markup

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>
Code behind (C#)
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";
        }
    }
}
Vb.Net
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>
C#
where xFi.Element("Category").Value.ToLower().Contains("programming")
Vb.Net
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.

← PreviousNext →