Stuck on basic Linq to XML query

2019-07-18 15:19发布

I'm trying to extract the information from the namecheap sandbox api and can't figure out why my linq queries aren't working.

Here's a sample response.

XML

<ApiResponse Status="OK" xmlns="http://api.namecheap.com/xml.response">
  <Errors />
  <Warnings />
  <RequestedCommand>namecheap.domains.check</RequestedCommand>
  <CommandResponse>
    <DomainCheckResult Domain="google.com" Available="false" />
  </CommandResponse>
  <Server>WEB1-SANDBOX1</Server>
  <GMTTimeDifference>--4:00</GMTTimeDifference>
  <ExecutionTime>0.875</ExecutionTime>
</ApiResponse>

C#

var doc = XDocument.Load(url);
var response = (
    from  r in doc.Root.Descendants("ApiResponse") 
    where 1==1
    select new  { 
        Errors = r.Element("Errors").Value,
        Warnings = r.Element("Warnings").Value,
        RequestedCommand = r.Element("RequestedCommand").Value,
        CommandResponse = r.Element("CommandResponse").Value,
        Server = r.Element("Server").Value
    }
);

I've also tried this query with the same doc just to see if a simple example worked.

var test = doc.Descendants("RequestedCommand").First().Value;

But both return null. So where am I going wrong? I'll eventually need to get at the top level elements and the deeper elements within CommandResponse. Any help with that would also be appreciated.

UPDATE

As Jon's answer mentioned, it was mainly an issue with not using the namespace when referencing the various elements. Also used doc.Elements() rather then doc.Root. Descendants().

Here's an updated working version.

XNamespace ns = "http://api.namecheap.com/xml.response";
var response = (
    from r in doc.Elements()
    select new
    {
        Errors = r.Element(ns + "Errors").Value,
        Warnings = r.Element(ns + "Warnings").Value,
        RequestedCommand = r.Element(ns + "RequestedCommand").Value,
        CommandResponse = r.Element(ns + "CommandResponse").Value,
        Server = r.Element(ns + "Server").Value
    }
);

2条回答
Emotional °昔
2楼-- · 2019-07-18 15:29

The problem is that you're not using the namespace when you're looking for elements, descendants etc:

XNamespace ns = "http://api.namecheap.com/xml.response";
var doc = XDocument.Load(url);
var response = doc.Root
                  .Descendants(ns + "ApiResponse")
                  .Select(r => new {
                              Errors = r.Element(ns + "Errors").Value,
                              ...
                          });

(Note that you never need where 1 == 1 in LINQ... I've changed this from query expression syntax as it wasn't giving you anything.)

The namespace is inherited from the <ApiResponse> element as the default namespace for all the other elements, as it's just xmlns=... rather than specifying an alias.

Also note that if you've shown us the whole XML document, then the above won't find any elements, as you're asking for ApiReponse elements below the root element, whereas it is the root element.

查看更多
\"骚年 ilove
3楼-- · 2019-07-18 15:38

I just got Skeeted ;)

Here's something I did in linqpad to get you one of the elements in the XML

var myxml = @"<ApiResponse Status=""OK"" xmlns=""http://api.namecheap.com/xml.response"">
<Server>WEB1-SANDBOX1</Server>
<Errors />
<Warnings />
<RequestedCommand>namecheap.domains.check</RequestedCommand>
<CommandResponse>
    <DomainCheckResult Domain=""google.com"" Available=""false"" />
</CommandResponse>

<GMTTimeDifference>--4:00</GMTTimeDifference>
<ExecutionTime>0.875</ExecutionTime>
</ApiResponse>";

//myxml.Dump();

XNamespace p = "http://api.namecheap.com/xml.response";
var doc1 = XElement.Parse(myxml);
var x = from n in doc1.Elements(p + "Server")  select n;
x.First().Value.Dump();
查看更多
登录 后发表回答