How to Read XML element attributes with XElement in LINQ

By FoxLearn 3/1/2025 3:49:33 AM   4
XML elements can contain attributes, which are key-value pairs. To read these attributes, you can use XElement to parse the XML string (from the LINQ-to-XML API).

Once you have parsed the XML, you can use these two methods to retrieve attributes:

  • XElement.Attribute(name): Retrieves a single attribute by name (as XAttribute). This is case-sensitive.
  • XElement.Attributes(): Retrieves all attributes of the element (as IEnumerable<XAttribute>).

Once you have the attributes, you can use the XAttribute.Value property to read the attribute’s string value.

Here’s an example where we read all the Book elements and output their attribute values:

using System.Linq;
using System.Xml.Linq;

var xmlString =
"""
<Library>
    <Book id="101" genre="fiction">The Great Gatsby</Book>
    <Book id="102" genre="non-fiction">Sapiens: A Brief History of Humankind</Book>
    <Book id="103" genre="mystery">Gone Girl</Book>
</Library>
""";

var libraryXml = XElement.Parse(xmlString);

foreach (var book in libraryXml.Descendants("Book"))
{
    var title = book.Value;
    var id = book.Attribute("id").Value;
    var genre = book.Attribute("genre").Value;

    Console.WriteLine($"Book {id} is '{title}' ({genre})");
}

Output:

Book 101 is 'The Great Gatsby' (fiction)
Book 102 is 'Sapiens: A Brief History of Humankind' (non-fiction)
Book 103 is 'Gone Girl' (mystery)

Find XML Elements by Attribute Values

You can use LINQ methods to search for XML elements based on their attribute values.

For example, Using FirstOrDefault() to Find a Specific Book by ID

This example demonstrates how to use FirstOrDefault() to find the first element with a particular attribute value:

using System.Linq;
using System.Xml.Linq;

var xmlString =
"""
<Library>
    <Book id="101" genre="fiction">The Great Gatsby</Book>
    <Book id="102" genre="non-fiction">Sapiens: A Brief History of Humankind</Book>
    <Book id="103" genre="mystery">Gone Girl</Book>
</Library>
""";

var libraryXml = XElement.Parse(xmlString);
var book101 = libraryXml.Descendants("Book").FirstOrDefault(b => b.Attribute("id").Value == "101");

Console.WriteLine($"Book with id 101 = '{book101.Value}'");

Output:

Book with id 101 = 'The Great Gatsby'

For example, Using Where() to Find Books of a Specific Genre

This example uses Where() to find all elements with a specific attribute value:

var fictionBooks = libraryXml.Descendants("Book").Where(b => b.Attribute("genre").Value == "fiction");

Console.WriteLine($"There are {fictionBooks.Count()} fiction books");

Output:

There are 1 fiction books

Check if an Element’s Attribute Exists

The XElement.Attribute() method will return null if the attribute doesn't exist. You can null-check the XAttribute object to avoid a NullReferenceException.

For example: Null-Checking for a Missing Attribute

This example shows how to safely check for an attribute that might not exist:

using System.Xml.Linq;

var xmlString =
"""
<Library>
    <Book id="103">Gone Girl</Book>
</Library>
""";

var bookAttribute = XElement.Parse(xmlString).Element("Book").Attribute("genre");

if (bookAttribute == null)
    Console.WriteLine("Attribute 'genre' doesn't exist");

Console.WriteLine($"Attribute value={bookAttribute?.Value}");

Output:

Attribute 'genre' doesn't exist
Attribute value=

Change an Attribute’s Value

There are two main methods for changing an attribute’s string value:

  • XElement.SetAttributeValue(name, value): Modifies the value or inserts the attribute if it doesn't exist. Pass null to remove the attribute.
  • XAttribute.SetValue(value): Changes the value of an existing attribute.

Both methods convert the passed object to a string.

For example: Updating Book Attributes

In this example, we modify the attribute values of all Book elements:

using System.Xml.Linq;

var xmlString =
"""
<Library>
    <Book genre="fiction" available="true">The Great Gatsby</Book>
    <Book genre="non-fiction" available="true">Sapiens: A Brief History of Humankind</Book>
    <Book genre="mystery" available="false">Gone Girl</Book>
</Library>
""";

var libraryXml = XElement.Parse(xmlString);

foreach (var book in libraryXml.Descendants("Book"))
{
    // Update or insert the "available" attribute
    book.SetAttributeValue("available", "true");

    // Update the "genre" attribute based on the book title
    book.Attribute("genre").SetValue(book.Value.ToUpper());
}

Console.WriteLine(libraryXml);

Output:

<Library>
    <Book genre="THE GREAT GATSBY" available="true">The Great Gatsby</Book>
    <Book genre="SAPIENS: A BRIEF HISTORY OF HUMANKIND" available="true">Sapiens: A Brief History of Humankind</Book>
    <Book genre="GONE GIRL" available="true">Gone Girl</Book>
</Library>

In this case, the genre for each book is converted to uppercase, and the available attribute is set to true for all books, even if the original value was false.