An XML document has many elements in the form of attributes and Child attributes. To read each attribute, we will need a special method and LINQ provides this method in the form of Descendants().
We will see how we can use the descendants() method in our example to target a "specific" attribute and its child attributes to read data in XML.
Find All Elements in XML using LINQ to XML Features
Before we begin, we need to create an XML document or a file. It’s a library of books. Yes, I have used this document many times in many articles before. Its simple and here you will find the XML file.
You must create a file with the extension “.xml” and name it library. Copy the contents as it is in the file and save the file in the root directory.
To enhance our web page, we need to add a few controls. A button and a label will suffice for this purpose. When the button is clicked, it will trigger an event to load the XML document. The label will then display the values found within the document.
<div>
<p>
<input id="bt" type="button" value="Extract" runat="server"
onserverclick="showXML" />
</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 showXML(object sender, EventArgs e) { lblXML.InnerHtml = ""; // CLEAR THE LABEL. // LOAD XML DOCUMENT. var xml_Doc = XDocument.Load(Server.MapPath("library.xml")); // LOOK FOR A SPECIFIC XML ELEMENT USING "Descendants". IEnumerable<XElement> allElements = from xEle in xml_Doc.Descendants("List") select xEle; // NOW, READ AND DISPLAY THE VALUES. foreach (XElement result in allElements) { 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 />"; } } }
To load an XML document into an object, I am using the XDocument class, which is provided by the System.Xml.Linq namespace. This class offers several useful methods, including the "Load"() method. By using this method, we can create a new XDocument by passing the XML document's path as a parameter.
Note: For Visual Basic, I am not importing the System.Xml.Linq
Option Explicit On Partial Class Site Inherits System.Web.UI.MasterPage Protected Sub showXML(ByVal sender As Object, ByVal args As EventArgs) lblXML.InnerHtml = "" ' CLEAR THE LABEL. ' LOAD XML DOCUMENT. Dim xml_Doc = XDocument.Load(Server.MapPath("library.xml")) Dim allElements As IEnumerable(Of XElement) ' LOOK FOR A SPECIFIC XML ELEMENT USING "Descendants". allElements = _ From xEle In xml_Doc.Descendants("List") _ Select xEle ' NOW, READ AND DISPLAY THE VALUES. For Each result As XElement In allElements 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 End Sub End Class
Result
Add More Child Elements
Now, this example is very straightforward. The XML document has a root node with an element <List>. Each <List> element has three child elements, such as, <BookName>, <Category> and <Price>.
However, we may add elements to our child elements too. For example, I’ll divide each book into multiple categories. Therefore, the first book in the library may fall under category computers and architecture. The structure will look like this.
The XML
<List> <BookName>Computer Architecture</BookName> <Category> <Cate1>Computer</Cate1> <Cate2>Architecture</Cate2> </Category> <Price>125.60</Price> </List>
Now, in <Category> node, I have added two more child elements, that is, <Cate1> and <Cate2>. Each has a unique value.
We need to modify a small piece of the code. To show different categories, I am using the Descendants() method again and this time inside the loop. The method will now look for descendant (or child) elements inside the <Category> element. That’s what we want.
foreach (XElement result in allElements) { lblXML.InnerHtml = lblXML.InnerHtml + "<br />" + "<b> Book Name: </b>" + result.Element("BookName") + "<br />" + "<b> Category: </b> " + result.Element("Category").Descendants("Cate1").ElementAt(0).Value + " and " + result.Element("Category").Descendants("Cate2").ElementAt(0).Value + "<br />" + "<b> Price: </b>" + result.Element("Price") + "<br />"; }
For Each result As XElement In allElements lblXML.InnerHtml = lblXML.InnerHtml & "<br />" & _ "<b> Book Name: </b>" & result.Element("BookName").Value & "<br />" & _ "<b> Category: </b> " & result.Element("Category").Descendants("Cate1").Value & _ " and " & result.Element("Category").Descendants("Cate2").Value & "<br />" & _ "<b> Price: </b>" & result.Element("Price").Value & "<br />" Next
The output will show two different categories.