Danny
Danny

Reputation: 1758

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 XDocument, 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">
  <entry>
    <content type="application/xml">
      <m:properties>
        <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>
      </m:properties>
    </content>
  </entry>
</feed>

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 null 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 d and m attributes, they use the namespace http://www.w3.org/2000/xmlns/, which must be the default. Why don't they use the namespace defined in the xmlns attribute like the elements do? Does the order of the attributes matter? Or maybe the xmlns namespace simply can't be overridden when used explicitly?

Upvotes: 1

Views: 731

Answers (1)

Mark Cidade
Mark Cidade

Reputation: 99997

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;

Upvotes: 1

Related Questions