Linq To Xml problems using XElement's method Elements(XName)

Dorian McHensie picture Dorian McHensie · May 2, 2010 · Viewed 8.6k times · Source

I have a problem using Linq To Xml.

A simple code. I have this XML:

<?xml version="1.0" encoding="utf-8" ?>
<data xmlns="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/directory file.xsd">
<contact>
 <name>aaa</name>
 <email>[email protected]</email>
 <birthdate>2002-09-22</birthdate>
 <telephone>000:000000</telephone>
 <description>Description for this contact</description>
</contact>
<contact>
 <name>sss</name>
 <email>[email protected]</email>
 <birthdate>2002-09-22</birthdate>
 <telephone>000:000000</telephone>
 <description>Description for this contact</description>
</contact>
<contact>
 <name>bbb</name>
 <email>[email protected]</email>
 <birthdate>2002-09-22</birthdate>
 <telephone>000:000000</telephone>
 <description>Description for this contact</description>
</contact>
<contact>
 <name>ccc</name>
 <email>[email protected]</email>
 <birthdate>2002-09-22</birthdate>
 <telephone>000:000000</telephone>
 <description>Description for this contact</description>
</contact>

I want to get every contact mapping it on an object Contact. To do this I use this fragment of code:

XDocument XDoc = XDocument.Load(System.Web.HttpRuntime.AppDomainAppPath + this.filesource);
XElement XRoot = XDoc.Root;
//XElement XEl = XElement.Load(this.filesource);
var results = from e in XRoot.Elements("contact") 
 select new Contact((string)e.Element("name"), (string)e.Element("email"), "1-1-1", null, null);
List<Contact> cntcts = new List<Contact>();
foreach (Contact cntct in results) {
 cntcts.Add(cntct);
}
Contact[] c = cntcts.ToArray();
// Encapsulating element
Elements<Contact> final = new Elements<Contact>(c);

Ok just don't mind that all: focus on this:

When I get the root node, it is all right, I get it correctly.

When I use the select directive I try to get every node saying: from e in

XRoot.Elements("contact")

OK here's the problem: if I use: from e in XRoot.Elements() I get all contact nodes, but if I use: from e in XRoot.Elements("contact") I GET NOTHING: Empty SET.

OK you tell me: Use the other one: OK I DO SO, let's use: from e in XRoot.Elements(), I get all nodes anyway, THAT's RIGHT BUT HERE COMES THE OTHER PROBLEM: When Saying: select new Contact((string)e.Element("name"), (string)e.Element("email"), "1-1-1", null, null); I Try to access <name>, <email>... I HAVE TO USE .Element("name") AND IT DOES NOT WORK TOO!!!!!!!!WHAT THE HELL IS THIS????????????? IT SEEMS THAT I DOES NOT MATCH THE NAME I PASS But how is it possible. I know that Elements() function takes, overloaded, one argument that is an XName which is mapped onto a string. Please consider that the code I wrote come from an example, It should work.

Answer

marc_s picture marc_s · May 2, 2010

Pretty easy: there's a XML namespace in play, which you're ignoring:

<data xmlns="http://www.example.com"  
      **************************

You need to add that to your Linq-to-XML queries!

Something like:

XNamespace ns = "http://www.example.com";

and then

XRoot.Elements(ns + "contact") 

and of course, also use the XML namespace when accessing the child elements:

var results = from e in XRoot.Elements("contact") 
              select new Contact(e.Element(ns + "name").Value, 
                                 e.Element(ns + "email").Value, 
                                 "1-1-1", null, null);

That should help. See the MSDN docs on Working with XML Namespaces for more details.