0

I am trying to deserialize this xml:

<?xml version="1.0" encoding="UTF-8"?>
<query xmlns:yahoo="http://www.yahooapis.com/v1/base.rng"
yahoo:count="10" yahoo:created="2012-02-20T19:07:02Z" yahoo:lang="en-US">
<results>
    <a href="/dir/index?sid=396545299">Books &amp; Authors</a>
    <a href="/dir/index?sid=396545374">Dancing</a>
    <a href="/dir/index?sid=396546034">Genealogy</a>
    <a href="/dir/index?sid=396545298">History</a>
    <a href="/dir/index?sid=396545310">Other - Arts &amp; Humanities</a>
    <a href="/dir/index?sid=396545300">Performing Arts</a>
    <a href="/dir/index?sid=396545231">Philosophy</a>
    <a href="/dir/index?sid=2115500137">Poetry</a>
    <a href="/dir/index?sid=396546419">Theater &amp; Acting</a>
    <a href="/dir/index?sid=396545309">Visual Arts</a>
</results>
</query>

This is by the way a xml that yahoo api returnes when queried for categories and subcategories.

This code that is supposed to deserialize it:

string query_string = "some_url";

        HttpWebRequest request = HttpWebRequest.Create
            (query_string) as HttpWebRequest;

        using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
        {
            StreamReader reader = new StreamReader(response.GetResponseStream());

            System.Xml.Serialization.XmlSerializer serializer = new 

            System.Xml.Serialization.XmlSerializer(typeof(queryA));

            queryA Q = (queryA)serializer.Deserialize(reader); // THIS IS WHERE THE EXCEPTION IS THROWN

            reader.Close();
        }

and I get an exception saying: There is an error in XML document (2, 2).

Exception details:

"<query xmlns=''> was not expected."

Here's the class:

namespace Yahoo_answers_tool {
using System.Xml.Serialization;


/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class queryA {

    private queryResultsA[] resultsField;

    private string countField;

    private string createdField;

    private string langField;

    /// <remarks/>
    [System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlArrayItemAttribute("a", typeof(queryResultsA), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public queryResultsA[] results {
        get {
            return this.resultsField;
        }
        set {
            this.resultsField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified, Namespace="http://www.yahooapis.com/v1/base.rng")]
    public string count {
        get {
            return this.countField;
        }
        set {
            this.countField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified, Namespace="http://www.yahooapis.com/v1/base.rng")]
    public string created {
        get {
            return this.createdField;
        }
        set {
            this.createdField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified, Namespace="http://www.yahooapis.com/v1/base.rng")]
    public string lang {
        get {
            return this.langField;
        }
        set {
            this.langField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class queryResultsA {

    private string hrefField;

    private string valueField;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string href {
        get {
            return this.hrefField;
        }
        set {
            this.hrefField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTextAttribute()]
    public string Value {
        get {
            return this.valueField;
        }
        set {
            this.valueField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class NewDataSetA {

    private queryA[] itemsField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("query")]
    public queryA[] Items {
        get {
            return this.itemsField;
        }
        set {
            this.itemsField = value;
        }
    }
}

}

Any Ideas?

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
Igor
  • 1,532
  • 4
  • 23
  • 44
  • I suspect it doesn't like the namespace. – CodesInChaos Feb 21 '12 at 11:05
  • Which tool generated that code? I use Xsd2Code and never had such a problem. Your generated code looks odd to me (naming of classes) – BlueM Feb 21 '12 at 11:08
  • Have you tried what's described here? [Error Deserializing Xml to Object - xmlns='' was not expected][1] [1]: http://stackoverflow.com/questions/4884383/error-deserializing-xml-to-object-xmlns-was-not-expected – Nanhydrin Feb 21 '12 at 11:13
  • 1
    Why are you deserializing it, why not simply use Linq To Xml, or other XML perser, to just grab the data you are after? – Lloyd Feb 21 '12 at 11:15
  • @BlueM I am using XSD.exe that comeswith visual studio – Igor Feb 21 '12 at 11:50
  • @Nanhydrin Have I tried what? I don't know what to try. – Igor Feb 21 '12 at 11:51
  • @Lloyd Is Linq easier, any links to how to do it? – Igor Feb 21 '12 at 11:52
  • You have [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)] yet the Namespace is http://www.yahooapis.com/v1/base.rng. – Lloyd Feb 21 '12 at 11:54
  • @Lloyd I tried changing it to "http://www.yahooapis.com/v1/base.rng" for the queryA class and I still got the same error. – Igor Feb 21 '12 at 11:58
  • As Lloyd said, you have: [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)], have you tried simplifying it as shown in the accepted answer on that link so it's like: [System.Xml.Serialization.XmlRootAttribute("query")] – Nanhydrin Feb 21 '12 at 11:59
  • @user1188712 Updated answer shows working code, a lot less lines than Deserializing it! – Lloyd Feb 21 '12 at 12:24
  • @Nanhydrin Tried and still the same error. I guess I'll have to try what Lloyd suggested. – Igor Feb 21 '12 at 12:37

1 Answers1

1

As per my comment, I would parse the XML using Linq to Xml, the code below works however I would suggest separating the parsing outside of the Using statement so that you can dispose of the Response and Streamreader.

    public static YahooQueryResult LoadYahooResults(string url)
    {
        YahooQueryResult result = null;

        WebRequest request = WebRequest.Create(path);
        request.Timeout = 5000;

        try
        {
            using (WebResponse response = request.GetResponse())
            {                                                                                        
                XDocument doc = XDocument.Load(response.GetResponseStream());

                if (doc != null)
                {
                    var query = doc.Root;

                    // Query Attribute Values
                    var count = int.Parse(query.Attributes().First(c => c.Name.LocalName == "count").Value);
                    var created = query.Attributes().First(c => c.Name.LocalName == "created").Value;
                    var lang = query.Attributes().First(c => c.Name.LocalName == "lang").Value;
                    var results = doc.Descendants().FirstOrDefault(r => (r.Name.LocalName == "results")).Descendants().Select(a => new Result() { ID = int.Parse(a.Attribute("href").Value.Replace("/dir/index?sid=", string.Empty).Trim()), Href = a.Attribute("href").Value, Text = a.Value }).ToList();

                    result = new YahooQueryResult() { Lang = lang, Created = created, Count = count, Results = results };

                }
            }
        }
        catch (Exception ex)
        {
            // Handle Exception
        }

        return result;
    }


    public class Result
    {
        public int ID { get; set; }
        public string Href { get; set; }
        public string Text { get; set; }
    }

    public class YahooQueryResult
    {
        public string Lang { get; set; }
        public string Created { get; set; }
        public int Count { get; set; }
        public IEnumerable<Result> Results { get; set; }

    }
Lloyd
  • 2,932
  • 2
  • 22
  • 18
  • Thanks for this, I try it and let you know how it goes. Is there a way to get the ID number in the href link from the results as well as the values? – Igor Feb 21 '12 at 12:44
  • @user1188712 if its as simple as removing the '/dir/index?sid=' then change the code and add ID and add this code... ID = int.Parse(a.Attribute("href").Value.Replace("/dir/index?sid", string.Empty).Trim()) – Lloyd Feb 21 '12 at 12:50
  • Thanks a lot, this works nicely. Can you add the code of your last comment so it contains ID variable too? And one more question - howwould you handle the exception after try? – Igor Feb 21 '12 at 13:28
  • @user1188712 lucky I'm bored this afternoon! – Lloyd Feb 21 '12 at 13:46
  • @user1188712 sign on with a real ID and learn to contribute, right or wrong it makes everyone better programmers! – Lloyd Feb 21 '12 at 21:01