C# – Read XML element attributes with XElement (Linq)

XML elements can have attributes, which are key-value pairs. To read the attributes, use XElement to parse the XML string (from the Linq-to-Xml API). Then you can use these two methods for getting attributes:

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

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

Here’s an example of getting all elements named Movie and then outputting their attribute values:

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

var xmlString =
"""
<Movies>
	<Movie id="123" genre="comedy">Office Space</Movie>
	<Movie id="456" genre="action">John Wick</Movie>
	<Movie id="789" genre="action">Jurassic Park</Movie>
</Movies>
""";

var moviesXml = XElement.Parse(xmlString);

foreach (var movie in moviesXml.Descendants("Movie"))
{
	var name = movie.Value;
	var id = movie.Attribute("id").Value;
	var genre = movie.Attribute("genre").Value;

	Console.WriteLine($"Movie {id} is {name} ({genre})");
}
Code language: C# (cs)

This outputs the following:

Movie 123 is Office Space (comedy)
Movie 456 is John Wick (action)
Movie 789 is Jurassic Park (action)Code language: plaintext (plaintext)

Find XML elements by attribute values

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

Here’s an example of using FirstOrDefault() to look for the first element with a specific attribute value:

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

var xmlString =
"""
<Movies>
	<Movie id="123" genre="comedy">Office Space</Movie>
	<Movie id="456" genre="action">John Wick</Movie>
	<Movie id="789" genre="action">Jurassic Park</Movie>
</Movies>
""";

var moviesXml = XElement.Parse(xmlString);
var movie123 = moviesXml.Descendants("Movie").FirstOrDefault(m => m.Attribute("id").Value == "123");

Console.WriteLine($"Movie with id 123 = {movie123.Value}");
Code language: C# (cs)

Note: For querying XML, I suggest using Linq methods instead of query syntax. It’s simpler.

This outputs the value of the XML element it found:

Movie with id 123 = Office SpaceCode language: plaintext (plaintext)

Here’s an example of using Where() to find all elements containing a specific attribute value:

var actionMovies = moviesXml.Descendants("Movie").Where(m => m.Attribute("genre").Value == "action");

Console.WriteLine($"There are {actionMovies.Count()} action movies");
Code language: C# (cs)

This outputs the number of elements it found:

There are 2 action moviesCode language: plaintext (plaintext)

Check if an element’s attribute exists

XElement.Attribute() returns null if the attribute doesn’t exist. If necessary, you can null-check the XAttribute object to prevent getting a NullReferenceException.

Here’s an example. This is trying to get an attribute that doesn’t exist and then null-checking:

using System.Xml.Linq;

var xmlString =
"""
<Movies>
    <Movie id="789">Jurassic Park</Movie>
</Movies>
""";

var movieAttribute = XElement.Parse(xmlString).Element("Movie").Attribute("fake");

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

Console.WriteLine($"Attribute value={movieAttribute?.Value}");
Code language: C# (cs)

Without null-checking, this would throw NullReferenceException. Instead, it outputs the following:

Attribute doesn't exist
Attribute value=Code language: plaintext (plaintext)

Change an attribute’s value

There are two methods you can use for changing an attribute’s string value:

  • XElement.SetAttributeValue(name, value): Changes the value OR inserts the attribute if it doesn’t exist. Note: Pass in null to delete the attribute.
  • XAttribute.SetValue(value).

Note: Both of these convert the passed in object to a string for you.

Use whichever method makes sense in your situation. Just be aware that SetAttributeValue() can add / remove attributes so you don’t run into surprises.

Here’s an example of using these methods to modify the attribute values of all Movie elements:

using System.Xml.Linq;

var xmlString =
"""
<Movies>
	<Movie genre="comedy" streamable="false">Office Space</Movie>
	<Movie genre="action" streamable="false">John Wick</Movie>
	<Movie genre="action">Jurassic Park</Movie>
</Movies>
""";

var moviesXml = XElement.Parse(xmlString);

foreach(var movie in moviesXml.Descendants("Movie"))
{
    //Update or insert attribute
    movie.SetAttributeValue("streamable", true);

    //Update from existing
    movie.Attribute("genre").SetValue(movie.Value.ToUpper());
}

Console.WriteLine(moviesXml);
Code language: C# (cs)

Note: You can also use the XAttribute.Value property to set the attribute’s string value. This isn’t as flexible as these other two methods.

This outputs the following XML with changed attribute values:

<Movies>
  <Movie genre="OFFICE SPACE" streamable="true">Office Space</Movie>
  <Movie genre="JOHN WICK" streamable="true">John Wick</Movie>
  <Movie genre="JURASSIC PARK" streamable="true">Jurassic Park</Movie>
</Movies>
Code language: HTML, XML (xml)

It upper-cased all the genres and set the streamable attribute to true. For the last element (Jurassic Park), it inserted the missing streamable attribute.

Leave a Comment