Danny Danny - 11 months ago 95
C# Question

Parsing attributes with namespaces with XDocument

I am trying to parse the XML provided by the U.S. Treasury on their website here using LINQ's

, and I am running into issues when trying to parse out the namespaces programatically.

XDocument doc = XDocument.Load("http://data.treasury.gov/feed.svc/DailyTreasuryYieldCurveRateData?$filter=year(NEW_DATE)%20eq%202016");

Here is a stripped-down version of their XML:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xml:base="http://data.treasury.gov/Feed.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
<content type="application/xml">
<d:NEW_DATE m:type="Edm.DateTime">2016-01-04T00:00:00</d:NEW_DATE>
<d:BC_1YEAR m:type="Edm.Double">0.61</d:BC_1YEAR>

If I hard-code the namespaces to access the m:* and d:* elements to the values as they're defined in the root like so:

XNamespace ns = "http://www.w3.org/2005/Atom";
XNamespace m = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
XNamespace d = "http://schemas.microsoft.com/ado/2007/08/dataservices";

then I can parse out the value of a date with

Convert.ToDateTime(doc.Root.Element(ns + "entry").Element(ns + "content").Element(m + "properties").Element(d + "NEW_DATE"));

and it works fine. But I would rather not hard-code the namespaces, so I am trying to pull them out of the root using a similar method but I get
values back:

XNamespace ns = doc.Root.Attribute("xmlns").Value; // gives "http://www.w3.org/2005/Atom"
XNamespace m = doc.Root.Attribute(ns + "m").Value; <--- ERROR because the attribute is null
XNamespace d = doc.Root.Attribute(ns + "d").Value; <--- ERROR because the attribute is null

It turns out if I inspect the
attributes, they use the namespace
, which must be the default. Why don't they use the namespace defined in the
attribute like the elements do? Does the order of the attributes matter? Or maybe the
namespace simply can't be overridden when used explicitly?

Answer Source

The name of the attribute is xmlns:d. xmlns is reserved by the XML Namespaces standard. Any attribute or element starting with xml or XML is reserved by the XML standard. The attribute xmlns specifies the default namespace for the element or document.

 XNamespace d = doc.Root.Attribute(XNamespace.Xmlns+"d").Value;
 XNamespace m = doc.Root.Attribute(XNamespace.Xmlns+"m").Value;