Why do I have trouble using linq on XML with namespaces?

Hello,

I have a class that parses XML from a string and sets the values from the XML to the class properties. I can parse an XML string fine except when a tag has a namespace attribute (xmlns). When I have the namespace included I get an index out of range error on the .ElementAt(0).

An exmaple of _responseXML is

<NetConnectResponse xmlns="http://www.experian.com/NetConnectResponse">
  <CompletionCode>0000</CompletionCode>
  <ReferenceId></ReferenceId>
  <Products xmlns="http://www.experian.com/ARFResponse">
    <CreditProfile>
      <Header>
        <ReportDate>08222010</ReportDate>
        <ReportTime>161300</ReportTime>
        <Preamble>TCA5</Preamble>
        <ARFVersion>07</ARFVersion>
      </Header>
      ...
      ...

Thanks for the help!
-gtar


//load response into XDoc
        xdoc = XDocument.Parse(_responseXML);

 
       //create assimble reportDateTime
        var header = from h in xdoc.Descendants("Header")
                     select new
                     {
                         ReportDate = h.Element("ReportDate").Value,
                         ReportTime = h.Element("ReportTime").Value
                     };

        //set linq vars to local vars
        string rawDate = header.ElementAt(0).ReportDate;
        string rawTime = header.ElementAt(0).ReportTime;

Open in new window

gtarAsked:
Who is Participating?
 
chapmanjwConnect With a Mentor Commented:
Here is Microsoft's article on using XML namespaces with LINQ: http://msdn.microsoft.com/en-us/library/bb669152.aspx
0
 
nmarunCommented:
Try something like this:

xdoc = XDocument.Parse(_responseXML);
XNamespace xNamespace = "http://www.experian.com/ARFResponse";

//create assimble reportDateTime
var header = from h in xdoc.Descendants(xNamespace + "Header")
             select new
             {
                   ReportDate = h.Element(xNamespace + "ReportDate").Value,
                   ReportTime = h.Element(xNamespace + "ReportTime").Value
             };

Arun

0
 
Fernando SotoRetiredCommented:
Hi gtar;

I have corrected the code you placed in the question. You have two issues. One is that you need to use the namespace for the nodes that it is assigned to in the XML, see code snippet comments and two the query would never execute because it needs to be enumerated so I added the ToList() which will do the job.

Fernando
//load response into XDoc
xdoc = XDocument.Parse(_responseXML);

// Namespace to be used for child elements off the Root node
// except for the element Products and its child nodes which have 
// another namespace. 
XNamespace rns = "http://www.experian.com/NetConnectResponse";
// Namesapce to be used on the Products element and it child nodes
XNamespace pns = "http://www.experian.com/ARFResponse";

//create assimble reportDateTime
var header = (from h in xdoc.Descendants(pns + "Header")
              select new
              {
                  ReportDate = h.Element(pns + "ReportDate").Value,
                  ReportTime = h.Element(pns + "ReportTime").Value
              }).ToList();

//set linq vars to local vars
string rawDate = header.ElementAt(0).ReportDate;
string rawTime = header.ElementAt(0).ReportTime;

Open in new window

0
 
gtarAuthor Commented:
All that was needed for my query to execute was to include the root <NetConnectResponse> namespace in the query.

I was able to execute the query without the toList() method. I'm unclear as to why this is needed. Are you saying that if I had several <Header> values that the ToList would ad them to a list and that my original query would not?

Thanks for all your help!

I awarded chapmanjw with the points because I read the suggested msdn article and resolved my problem before I saw the rest of the posts.

Do you have a better approach to accessing the header data. It seems awkward to do the following

header.ElementAt(0).ReportDate

Thanks again,
Gtar

        XNamespace xNamespace = "http://www.experian.com/NetConnectResponse";

        //create assimble reportDateTime
        var header = from h in xdoc.Descendants(xNamespace + "Header")
                     select new
                     {
                         ReportDate = h.Element(xNamespace + "ReportDate").Value,
                         ReportTime = h.Element(xNamespace + "ReportTime").Value
                     };

Open in new window

0
All Courses

From novice to tech pro — start learning today.