What does this Document Contain?
This document provides an overview of how LINQ can be used in creating and querying XML. This document provides the real time scenarios which we come across, while working with LINQ to XML, with pieces of code and easy to understand screenshots of output.
Who Can Read?
Everyone who is interested in exploring how to use LINQ in .NET, to play with XML.
How is this Useful to me?
This document does not discuss all the topics in depth, but will surely serve you as a quick start guide to work with LINQ to XML.
LINQ: Language Integrated Query is a Microsoft .NET Framework component that adds the native querying capabilities to .NET Languages.
What is LINQ to XML: In memory XML Programming interface that enables us to work with XML from within the .NET Framework programming languages.
Advantage of LINQ to XML: Integration with LINQ, which enables us to write queries on the in memory XML Document to retrieve collection of Elements and Attributes. These Linq queries are syntactically different from XPath but provide similar functionality.
Ease of using query results as parameters to XElement
and XAttribute
object constructors enabling an easy approach in creating XML Trees, which further enable easy transformation of the XML Trees from one shape to another.
Namespace which needs to be included in your code in order to work with LINQ to XML: System.Xml.Linq
.
Starting from .NET 3.5, Creating XML in .NET is made easy with LINQ (Language Integrated Query). Some important syntax changes in creating a XML document are here under.
XML in Older versions of .NET | XML Starting from .NET 3.5 |
XMLDocument | XDocument |
XMLElement | XElement |
XMLAttribute | XAttribute |
XMLNamespace | XNamespace |
XMLNode | XNode |
Creating a Simple XML
We are creating an XDocument
(nothing but an XML) with Employee
details like Name
, Id
and Designation
.
XDocument document = new XDocument(
new XElement("Employees",
new XElement("Name", "Krishna"),
new XElement("ID", "12345"),
new XElement("Designation", "Engineer")));
As shown in the above piece of code, it is as simple as mentioning a KEY, VALUE pair just like new XElement("Name", "Krishna")
.
And the output is:
Creating XML with Element Attributes
In most of the real time scenarios, we need to create XML with Element
attributes. Here is the code to create an Employees
XML with their designation as Element
attribute.
XDocument xDocument = new XDocument(
new XElement("Employees",
new XElement("Employee", "Pavan",
new XAttribute("Designation", "Developer")),
new XElement("Employee", "sudhir",
new XAttribute("Designation", "Tester"))));
Output:
Creating XML with Namespace
When creating an XDocument
with namespace, you have to explicitly add the namespace to the child element also (new XElement(myNamespace + "Employee", "sudhir")
, so that it will be inside the parent element namespace, as shown here.
XNamespace myNamespace = "https://www.microsoft.com";
XDocument xDocument = new XDocument(
new XElement(myNamespace + "Employees",
new XElement(myNamespace + "Employee", "Pavan",
new XAttribute("Designation", "Developer")),
new XElement(myNamespace + "Employee", "sudhir",
new XAttribute("Designation", "Tester"))));
And the output will be as shown below:
If you do not mention the namespace keyword (here it is “myNamespace
”) while adding child elements, the output will be as shown here under:
As spotted with a Red circle, we will get an empty attribute in all the Child Elements. So we need to append namespace for each Child Element while creating the XDocument
.
Working with Multiple Namespaces
Some scenarios expect us to have multiple namespaces in the XDocument
we create. One namespace is for Parent Node and the other for all the Child Nodes. In such cases, we need to use two different XNamespace
variables as shown below:
XNamespace firstNamespace = "https://www.microsoft.com";
XNamespace secondNamespace = "https://www.microsoft.com/myBlogs";
XDocument myDocument = new XDocument(
new XElement(firstNamespace + "Employees",
new XElement(firstNamespace + "Employee", "Senthil"),
new XElement(firstNamespace + "Employee", "Prabhu"),
new XElement(secondNamespace + "Employee", "Sampath"),
new XElement(secondNamespace + "Employee", "Kumar")));
Output:
Prefixing the Namespace
If we see the above example, in the output it looks messy to have the namespace URL in each and every Child
Element. In order to overcome this, we can include the second namespace also in the Parent Element and assign a keyword for it and then append this keyword while creating XElements
.
XDocument myDocument = new XDocument(
new XElement(firstNamespace + "Employees",
new XAttribute(XNamespace.Xmlns +"secondNamespace",secondNamespace),
new XElement(firstNamespace + "Employee", "Senthil"),
new XElement(firstNamespace + "Employee", "Prabhu"),
new XElement(secondNamespace + "Employee", "Sampath"),
new XElement(secondNamespace + "Employee", "Kumar")));
Output:
Saving the XML
We can save the created XDocument
to any location, as XML document:
XDocument xDoc = new XDocument(
new XElement("Friends",
new XElement("Friend", "Senthil"),
new XElement("Friend", "Prabhu")));
xDoc.Save(@"c:\myTest.xml");
When we go to the physical path and open the saved XML in browser, we can see as below:
Loading the Saved XML
We can load the saved XML document and create XDocument
using the below piece of code. Here I am loading the XML document and then binding the generated XDocument
to a string
variable.
XDocument myDoc = XDocument.Load(@"c:\myTest.xml");
string check = myDoc.ToString();
When we check with the string
variable in Text visualizer, it looks like below:
Methods of XElement Class
Attribute, Attributes, Element, Elements, Descendants, Ancestors.
There are many methods and it’s a big list to mention here. We will see how to make use of some of the most commonly used methods like the ones mentioned above.
- Element: Gives you the immediate Child Node
- Elements: Gives the collection of Child Elements of this element or document as per the document order
- Descendants: Gives you all the Child Nodes
- Attributes: Returns a collection of Attributes of this Element
- Attribute: Returns the
XAttribute
of this XElement
that has the specified XName
Getting Elements with a Specific Name
XDocument myDocument = new XDocument(
new XElement("Employees",
new XAttribute(XNamespace.Xmlns +"secondNamespace",secondNamespace),
new XElement(firstNamespace + "Employee", "Senthil"),
new XElement(firstNamespace + "Employee", "Prabhu"),
new XElement(secondNamespace + "Employee", "Sampath"),
new XElement(secondNamespace + "Employee", "Kumar")));
foreach (XElement myElement in myDocument.Descendants
(firstNamespace + "Employee"))
{
String sOne += (string)myElement;
}
foreach
statement is used to loop through all the values returned for Element “Employee
” and then these values are assigned to a string
variable. Explicit conversion is required while assigning the Element
value to a string
variable. And the output is:
In the same way, we can get the Element
attribute values, using the below query:
foreach (XElement myElement in xdoc.Descendants("Employee"))
{
foreach (XAttribute xAtt in myElement.Attributes())
{
String sTwo = (string)xAtt;
}
}
Parsing a string to XDocument
Consider a string
which contains XML, as shown below:
string myString =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<BankDetails>
<AccountHolder>Sai Krishna</AccountHolder>
<AccountNumber>12345678912</AccountNumber>
<AccountType>Savings</AccountType>
</BankDetails>";
Now, call the Parse
method in order to generate XDocument
from the above string
:
XDocument myXDoc = XDocument.Parse(myString);
Output:
Using Query operators on XDocument
Consider we need all the Director
names who direct “Action
” Type movie, from the below XDocument
.
XDocument xdoc = new XDocument(
new XElement("Directors",
new XElement("Director", "James cameron",
new XAttribute("Type", "Sci-Fi")),
new XElement("Director", "Guy Ritchie",
new XAttribute("Type", "Action")),
new XElement("Director", "clientEastwood",
new XAttribute("Type", "Action")),
new XElement("Director", "ManiRatnam",
new XAttribute("Type", "Sci-Fi"))));
The query which we need to write:
var myDirectors = from xE in xdoc.Descendants("Director")
where xE.Attribute("Type").Value == "Action"
orderby xE.Value
select xE.Value;
foreach (var Director in myDirectors)
{
Console.WriteLine(Director);
}
Output:
We get “Client Eastwood
” and “Guy Ritchie
” as they are having attribute type as “Action
”.
Appending Elements to Already Existing XDocument
Consider there is an XDocument
already created. We need to add couple of additional elements to the existing XDocument
. Say, we need to add two more employees details to the already existing Employee
XML tree. The code here shows you how to do that:
XDocument myDoc = new XDocument(
new XElement("SASTeam",
new XElement("Employee",
new XElement("Designer", "Naveen"),
new XElement("DBA", "Shankar")
)));
If we check this XDocument
, we will get the below XML tree.
Now, add two more employee
details as shown here:
myDoc.Root.Element("Employee").Add(
new XElement("Developer", "Kaipa"),
new XElement("Tester", "Kartheek"));
And the output is:
You can see in the output, that two employee details “Kaipa
” and “kartheek
” added to the existing Employee
Tree.
XDocument and String
Consider the XDocument
mentioned in the previous section. We can convert this to an XML string by just calling the Tostring()
method.
string myString = myDoc.ToString();
And the result string
value is:
myString =
"<SASTeam>\r\n <Employee>\r\n <Designer>Naveen</Designer>\r\n
<DBA>Shankar</DBA>\r\n <Developer>Kaipa</Developer>\r\n
<Tester>Kartheek</Tester>\r\n </Employee>\r\n</SASTeam>"
I can see that this is not what we expect. In order to remove the special characters like “\r\n”, we need to do as below, while assigning the XDocument
to string
.
string myString = myDoc.ToString(SaveOptions.DisableFormatting);
And the result string
is as shown below:
myString =
"<SASTeam><Employee><Designer>Naveen</Designer><DBA>Shankar</DBA>
<Developer>Kaipa</Developer><Tester>Kartheek</Tester></Employee></SASTeam>"
The default SaveOption
will be None (SaveOptions.None
). We need to switch between the options based on our requirement.
XDeclaration Issue
In the above section if we observe, there is no XDeclaration
in the XDocument
. We will create the same XDocument
, but with XDeclaration
this time:
XDocument myDoc = new XDocument(
new XDeclaration("1.0","utf-8","yes"),
new XElement("SASTeam",
new XElement("Employee",
new XElement("Designer", "Naveen"),
new XElement("DBA", "Shankar")
)));
Now if we check with the myString
, we will get:
In the result string
, we can see that XML Declaration is missing. To overcome this, we need to explicitly append the declaration string
as shown here:
string myString = myDoc.Declaration.ToString() +
myDoc.ToString(SaveOptions.DisableFormatting);
And now the string
value is:
Summary
LINQ to XML is the new approach in constructing, writing, reading and querying XML data using the latest .NET framework language capabilities. This new API simplifies working with XML and provides a superior developer experience.