C# Working with Namespaces in XDocument and XML

XDocument is your old XML friend in C#, and it allows you to create or manipulate XML documents. To work with namespaces, you must use the XNamespace class.

This is an imaginary XML document (a Google Merchant Feed formatted one) that we wish to manipulate:

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
	<channel>
		<item>
			<g:id>42069</g:id>
			<title>Brian Caos</title>
			<description>A developer</description>
			<link>https://briancaos.wordpress.com/</link>
			<g:image_link>https://briancaos.files.wordpress.com/2019/09/bp-small-e1567426409278.png</g:image_link>
			<g:availability>in stock</g:availability>
			<g:price>42.00 USD</g:price>
		</item>
	</channel>
</rss>

Notice that the XML have the namespace http://base.google.com/ns/1.0, but not all fields are namespaced. This is because the document is basically a RSS 2.0 feed with additional fields, and it’s only the additional fields that have the namespace.

READ THE DOCUMENT

To read the document from a string, you need an XDocument, and a XNamespace:

// Get the RSS 2.0 XML data
string feedData = {{feed string}}
 
// Convert the data into an XDocument
var document = XDocument.Parse(feedData);
// Specify the Google namespace
XNamespace g = "http://base.google.com/ns/1.0";

The {{feed string}} is of course the feed as described above.

The trick is that we now have the namespace in the variable called “g”. To add a namespace, you simply add the “g” variable in front of the element name, like this:

ADD AN ELEMENT WITH A NAMESPACE

If I would like to add a <g:availability>in_stock</g:availability> to every item in the XML document, I can do so like this:

// Get all elements with the name "item"
var items = document.Descendants().Where(node => node.Name == "item");
foreach (var item in items)
{
    // Create new element with namespace http://base.google.com/ns/1.0
    var id = new XElement(g + "availability", "in stock");
    // Add it to the document
    item.Add(id);
}

GET AN ELEMENT WITH A NAMESPACE

This will get all items with the element is <g:availability>out of stock</g:availability>:

items = document.Descendants()
  .Where(node => node.Name == "item"
         && node.Descendants()
         .Any(desc => desc.Name == g + "availability"
              && desc.Value == "out of stock"));

MORE TO READ:

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in .net, .NET Core, c#, General .NET and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.