views:

481

answers:

2

Hi all,

I have this code :

/*string theXml =
@"<Response xmlns=""http://myvalue.com""&gt;&lt;Result xmlns:a=""http://schemas.datacontract.org/2004/07/My.Namespace"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""&gt;&lt;a:TheBool&gt;true&lt;/a:TheBool&gt;&lt;a:TheId&gt;1&lt;/a:TheId&gt;&lt;/Result&gt;&lt;/Response&gt;";*/

string theXml = @"<Response><Result><TheBool>true</TheBool><TheId>1</TheId></Result></Response>";

XDocument xmlElements = XDocument.Parse(theXml);

var elements = from data in xmlElements.Descendants("Result")
               select new {
                            TheBool = (bool)data.Element("TheBool"),
                            TheId = (int)data.Element("TheId"),
                          };

foreach (var element in elements)
{
    Console.WriteLine(element.TheBool);
    Console.WriteLine(element.TheId);
}

When I use the first value for theXml, the result is null, whereas with the second one, I have good values ...

How to use Linq to Xml with xmlns values ?

Thanks in advance for your help.

+2  A: 

You can pass an XName with a namespace to Descendants() and Element(). When you pass a string to Descendants(), it is implicitly converted to an XName with no namespace.

To create a XName in a namespace, you create a XNamespace and concatenate it to the element local-name (a string).

XNamespace ns = "http://myvalue.com";
XNamespace nsa = "http://schemas.datacontract.org/2004/07/My.Namespace";

var elements = from data in xmlElements.Descendants( ns + "Result")
                   select new
                              {
                                  TheBool = (bool)data.Element( nsa + "TheBool"),
                                  TheId = (int)data.Element( nsa + "TheId"),
                              };

There is also a shorthand form for creating a XName with a namespace via implicit conversion from string.

var elements = from data in xmlElements.Descendants("{http://myvalue.com}Result")
                   select new
                              {
                                  TheBool = (bool)data.Element("{http://schemas.datacontract.org/2004/07/My.Namespace}TheBool"),
                                  TheId = (int)data.Element("{http://schemas.datacontract.org/2004/07/My.Namespace}TheId"),
                              };

Alternatively, you could query against XElement.Name.LocalName.

var elements = from data in xmlElements.Descendants()
                   where data.Name.LocalName == "Result"
Lachlan Roche
LocalName doesn't exists in my intellissense
Tim
+1  A: 

LINQ to XML methods like Descendants and Element take an XName as an argument. There is a conversion from string to XName that is happening automatically for you. You can fix this by adding an XNamespace before the strings in your Descendants and Element calls. Watch out because you have 2 different namespaces at work.


string theXml =
                @"true1";

            //string theXml = @"true1";

    XDocument xmlElements = XDocument.Parse( theXml );
    XNamespace ns = "http://myvalue.com";
    XNamespace nsa = "http://schemas.datacontract.org/2004/07/My.Namespace";
    var elements = from data in xmlElements.Descendants( ns + "Result" )
          select new
                 {
                     TheBool = (bool) data.Element( nsa + "TheBool" ),
                     TheId = (int) data.Element( nsa + "TheId" ),
                 };

    foreach ( var element in elements )
    {
        Console.WriteLine( element.TheBool );
        Console.WriteLine( element.TheId );
    }

Notice the use of ns in Descendants and nsa in Elements

Mike Two
great, working :) !! Thanks a lot
Tim
xmlElements.Descendants(xmlElements.Root.GetDefaultNamespace() + "Result") may work too...
Ollie Jones