LINQ to XML uses a document object model (DOM) that consists of classes such as XDeclaration, XDocument, XElement, XAttribute, etc. All these classes derive from the XNode class that provide the common API.
Example: Parse a string containing XML:
using System.Xml.Linq; ... // Parse an XML document. string xml = @"<?xml version='1.0' encoding='utf-8' standalone='yes'?> <books> <book id='1'> <title>Good Book</title> </book> <book id='2'> <title>Another Good Book</title> </book> </books>"; XDocument doc = XDocument.Parse(xml); // Parse an XML element. string xml = @"<book id='1'> <title>Good Book</title> </book>"; XElement book = XElement.Parse(xml);
Example: Load an XML file:
// from the web XDocument doc = XDocument.Load("http://mysite.com/test.xml"); // from a file XElement books = XElement.Load(@"c:\temp\books.xml");
Example: Construct an XML document. All the code snippets create the same XML structure:
<?xml version="1.0" encoding="utf-8"?> <books> <book id="1"> <title>Good Book</title> </book> <book id="2"> <title>Another Good Book</title> </book> </books>
using System.Xml.Linq; ... // Snippet #1: Use the XElement.Add method: XElement xml = new XElement("books"); XElement book1 = new XElement("book"); book1.Add(new XAttribute("id", 1)); book1.Add(new XElement("title", "Good Book")); xml.Add(book1); XElement book2 = new XElement("book"); book2.Add(new XAttribute("id", 2)); book2.Add(new XElement("title", "Another Good Book")); xml.Add(book2); // Snippet #2: Use functional construction: XElement xml = new XElement( new XElement("books", new XElement("book", new XAttribute("id", "1"), new XElement("title", "Good Book") ), new XElement("book", new XAttribute("id", "2"), new XElement("title", "Another Good Book") ) ) ); // Snippet #3: Pass an array of elements to the XElement constructor: var list = new List<XElement>(); list.Add(new XElement("book", new XAttribute("id", "1"), new XElement("title", "Good Book"))); list.Add(new XElement("book", new XAttribute("id", "2"), new XElement("title", "Another Good Book"))); XElement xml = new XElement( new XElement("books", list) ); // Show XML Console.WriteLine(xml); // Save XML in a file. xml.Save("books.xml");
Example: An example of automatic deep cloning:
using System.Xml.Linq; ... XElement author = new XElement("author", new XElement("firstName", "John"), new XElement("lastName", "Makak")); // The 'author' element is cloned in both 'book' elements. XElement book1 = new XElement("book", new XAttribute("id", "1"), new XElement("title", "Good Book"), author); Console.WriteLine(book1); XElement book2 = new XElement("book", new XAttribute("id", "2"), new XElement("title", "Another Good Book"), author); book2.Element("author").Element("lastName").Value = "Gibbon"; // modify the copy of the author element Console.WriteLine(book2);
Output:
<book id="1"> <title>Good Book</title> <author> <firstName>John</firstName> <lastName>Makak</lastName> </author> </book> <book id="2"> <title>Another Good Book</title> <author> <firstName>John</firstName> <lastName>Gibbon</lastName> </author> </book>
Example: Project a collection of books into XML. Use XStreamingElement rather than XElement to improve performance:
class Program { static void Main(string[] args) { var books = new List<Book>(); books.Add(new Book { Id = 1, Title = "Good Book" }); books.Add(new Book { Id = 2, Title = "Nice Book" }); var xml = new XStreamingElement("books", from b in books select new XStreamingElement("book", new XAttribute("id", b.Id), new XElement("title", b.Title) ) ); // <books> // <book id="1"> // <title>Good Book</title> // </book> // <book id="2"> // <title>Nice Book</title> // </book> // </books> Console.WriteLine(xml); } } public class Book { public int Id { get; set; } public string Title { get; set; } }
Example: Find the first element and the last one. Then, display all the elements of the XML document:
using System.Xml.Linq; ... string xml = @"<books> <book id='1'> <title>Good Book</title> </book> <book id='2'> <title>Another Good Book</title> </book> </books>"; XElement books = XElement.Parse(xml); // <book id="1"><title>Good Book</title></book> Console.WriteLine(books.FirstNode); // <book id="2"><title>Another Good Book</title></book> Console.WriteLine(books.LastNode); // <book id="1"><title>Good Book</title></book> // <book id="2"><title>Another Good Book</title></book> foreach (XNode node in books.Nodes()) Console.WriteLine(node); // Good Book // Another Good Book foreach (XElement element in books.Elements()) Console.WriteLine(element.Value);
Example: Find all the books which title (actually any element) contains the word “Another”. Return a collection of Id and Title pairs:
using System.Xml.Linq; ... string xml = @"<books> <book id='1'><title>Good Book</title></book> <book id='2'><title>Another Good Book</title></book> <book id='3'><title>Nice Book</title></book> <book id='4'><title>Another Nice Book</title></book> </books>"; XElement books = XElement.Parse(xml); var query = from book in books.Elements() // books.Elements() returns IEnumerable<> where book.Elements().Any(b => b.Value.Contains("Another")) // if you wanted to find the word "Another" only in the 'title' elements: // where book.Element("title").Value.Contains("Another") // when the 'title' element may not exist (for example, when it is optional): // where book.Element("title")?.Value.Contains("Another") select new { Id = book.Attribute("id").Value, Title = book.Element("title").Value }; // Id: 2, Title: Another Good Book // Id: 4, Title: Another Nice Book foreach (var book in query) Console.WriteLine("Id: {0}, Title: {1}", book.Id, book.Title);
Example: Find all the 'box' elements:
string xml = @"<things> <box>Box1</box> <pencil>Pencil1</pencil> <box>Box2</box> <eraser>Eraser1</eraser> <box>Box3</box> </things>"; XElement things = XElement.Parse(xml); var query = things.Elements("box"); // <box>Box1</box> // <box>Box2</box> // <box>Box3</box> foreach (var box in query) Console.WriteLine(box);
Example: Find all authors using chained sequences:
using System.Xml.Linq; ... string xml = @"<books> <book> <title>Book1</title> <author>AuthorA</author> </book> <book> <title>Book2</title> <author>AuthorB</author> </book> <book> <title>Book3</title> <author>AuthorC</author> </book> </books>"; XElement books = XElement.Parse(xml); var query = from author in books.Elements("book").Elements("author") select author; // AuthorA // AuthorB // AuthorC foreach (var author in query) Console.WriteLine(author.Value);
Example: List all the books using XElement.Descendants. Also, filter the books to show only those that have any reviews:
using System.Xml.Linq; ... string xml = @"<books> <book> <title>Book1</title> <author>AuthorA</author> <review>...</review> <review>...</review> </book> <book> <title>Book2</title> <author>AuthorB</author> </book> <book> <title>Book3</title> <author>AuthorC</author> <review>...</review> </book> </books>"; XElement books = XElement.Parse(xml); // Show all the books. IEnumerable<string> titles = from b in books.Descendants("book") select (string)b.Element("title") + ", " + (string)b.Element("author"); // Book1, AuthorA // Book2, AuthorB // Book3, AuthorC foreach (string title in titles) Console.WriteLine(title); // Show the books that have any reviews. IEnumerable<string> filtered = from b in books.Descendants("book") where b.Descendants("review").Any() let title = (string)b.Element("title") + ", " + (string)b.Element("author") orderby title select title; // Book1, AuthorA // Book3, AuthorC foreach (string title in filtered) Console.WriteLine(title);
Methods to update XML:
Example: Update an XML element using the SetValue method and the Value property:
string xml = @"<books> <book id='1'><title>Good Book</title></book> <book id='2'><title>Another Good Book</title></book> </books>"; XElement books = XElement.Parse(xml); // books.Element("book") selects the first book element. // Method #1 books.Element("book").SetValue("Discountinued"); // Method #2 books.Element("book").Value = "Discountinued"; // <books> // <book id="1">Discountinued</book> // <book id="2"><title>Another Good Book</title></book> // </books> Console.WriteLine(books);
Example: Add or update elements and attributes using SetElementValue and SetAttributeValue:
XElement things = new XElement("things"); things.SetAttributeValue("count", 1); // add an attribute on <things> things.SetElementValue("pencil", "aaa"); // add a child node things.SetElementValue("mug", "bbb"); // add a child node things.SetElementValue("notebook", "ccc"); // add a child node things.SetElementValue("mug", "zzz"); // update <mug> things.SetAttributeValue("count", 3); // update the attribute on <things> // <things count="3"> // <pencil>aaa</pencil> // <mug>zzz</mug> // <notebook>ccc</notebook> // </things> Console.WriteLine(things);
Example: Add an 'isKindle' attribute to all book elements:
string xml = @"<books> <book id='1'><title>Good Book</title></book> <book id='2'><title>Another Good Book</title></book> </books>"; XElement books = XElement.Parse(xml); XElement updated = new XElement("books", from b in books.Descendants("book") let title = b.Element("title") select new XElement("books", new XAttribute("isKindle", false), b.Attributes(), // include existing attributes i.e., the 'id' attribute title // 'title' represents the entire element i.e., <title>Good Book</title> ) ); Console.WriteLine(updated);
Output:
<books> <books isKindle="false" id="1"> <title>Good Book</title> </books> <books isKindle="false" id="2"> <title>Another Good Book</title> </books> </books>
// Create a namespace. XNamespace ns = "http://something.com/stuff/2016"; // Create elements within a default namespace ns. Note that the + operator is overloaded. var xml = new XElement(ns + "books", from b in books // books is a collection of books select new XElement(ns + "Book", new XAttribute("title", b.Title)) ); // Create elements within a different namespace (without a prefix). XNamespace ext = "http://something.com/stuff/2016/extended"; var xml = new XElement(ns + "books", from b in books select new XElement(ext + "Book", new XAttribute("title", b.Title)) ); // Create elements within a different namespace (with a prefix). XNamespace ext = "http://something.com/stuff/2016/extended"; var xml = new XElement(ns + "books", from b in books select new XElement(ext + "Book", new XAttribute("title", b.Title)) ); xml.Add(new XAttribute(XNamespace.Xmlns + "ext", ext));