Jerry
Jerry

Reputation: 1785

Clean up XML LINQ query

This is an offshoot of this question Stuck on basic Linq to XML query

I'm trying to get better at writing LINQ and learning about LINQ to XML. The LINQ query returns the results expected, but the code doesn't look clean. Is there a better way to write it?

XML

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

C#

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 = new
                      {
                         Domain= r.Element(ns + "CommandResponse").Element(ns + "DomainCheckResult").Attribute("Domain"),
                         Available = r.Element(ns + "CommandResponse").Element(ns + "DomainCheckResult").Attribute("Available")
                      },
       Server = r.Element(ns + "Server").Value
    });

Upvotes: 1

Views: 156

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500635

Well you're using a query expression for no reason, and you've got unnecessary brackets, and very long lines... but other than that it looks okay. One option to make it cleaner is to avoid using anonymous types - create a class (e.g. ApiResponse) with a FromXElement method, allowing you to write:

var response = doc.Elements().Select(x => ApiResponse.FromXElement(x));

Or in C# 4:

var response = doc.Elements().Select(ApiResponse.FromXElement);

You can then take the projection out of the query, and write it in a normal method. You could break that into several statements or not - it's your call.

It's still not clear whether you're really expecting more than one element, by the way - a document can only have one top level element, and if you're really only expecting the root element to be useful, then get rid of the querying part completely.

You might also find it clearer to avoid the string literals (and repeated ns + ... in your code, like this:

private static readonly XNamespace ResponseNs = 
    "http://api.namecheap.com/xml.response";
private static readonly XName ErrorsName = ResponseNs + "Errors";
private static readonly XName WarningsName = ResponseNs + "Warnings";
// etc

Then you can use:

Errors = r.Element(ErrorsName).Value

Upvotes: 2

Related Questions