0

I am trying to read xml from a sport odds feed, but I can't get it to work. I am using xmlReader.Create(url), but all I get is a data at the root level is invalid-error. This is what the code look like:

        XmlReader reader = XmlReader.Create("http://www.bet-at-home.com/oddxml.aspx");

        while (reader.Read())
        {

            if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "oo"))
            {
                //bla bla
            }
        }
Axel
  • 68
  • 1
  • 7
  • What is the full error? And why are you not using LINQ to XML? – It'sNotALie. May 31 '13 at 23:05
  • Unhandled Exception: System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1. at System.Xml.XmlTextReaderImpl.Throw(Exception e) at System.Xml.XmlTextReaderImpl.Throw(String res, String arg) at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace() at System.Xml.XmlTextReaderImpl.ParseDocumentContent() at System.Xml.XmlTextReaderImpl.Read() at Bet_At_Home.Program.Main(String[] args) in c:\users\hello world\documents\ visual studio 2010\Projects\... – Axel May 31 '13 at 23:09
  • 1
    @Axel That error indicates my previous comment was incorrect. It *is* fetching *something* (it could be an error response, too!), but the fetched data appears to be ill-formed XML (including HTML, which is not XML!). – user2246674 May 31 '13 at 23:17
  • Testing your link in a browser (IE) produced what appears to be valid XML - However, there is a 60 second delay between calls to that URI. Are you calling this URI more than once every 60 seconds? I was able to get your code sample to work by waiting 60+ seconds between tries. – Tim Jun 01 '13 at 01:33

2 Answers2

1

You need to make an httprequest to get the data. You can't just feed that method a url and expect it to treat it like a local file. First make an http request and save the the response in a string then you can process that like an xml. Here's a link to the HttpWebRequest for .NET http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx

evanmcdonnal
  • 46,131
  • 16
  • 104
  • 115
  • 1
    @Axel np, sorry my answer doesn't provide more details but I don't think the bug is with the xml reading. If you want to test it, copy and paste that response into a text file, save it locally and see that your xml reading logic works. After that you can implement the http part. Generally, it's helpful to decompose your problem into smaller pieces and do the most important ones first, in this case I would probably ignore the http GET until after you've implemented the xml reader and confirmed that it works. – evanmcdonnal Jun 01 '13 at 00:03
  • It is unlikly to help as `XmlReader` already correctly downloads data from Uri. Most likely data returned by the Url is simply not XML (Fiddler can easily show data send/received by an app, similar to browser) – Alexei Levenkov Jun 01 '13 at 00:15
  • @AlexeiLevenkov So the HttpWebRequest wont work? Actually the uri validated as xml at w3c. – Axel Jun 01 '13 at 00:28
  • @Axel - it may help as you'd have complete control over headers/be able to use proper encoding for response. You need to see what response actually coming back and if it is one you expect. – Alexei Levenkov Jun 01 '13 at 00:59
0

This is just a hunch, but if you try to access that URI more frequently than 60 seconds, you get the following message returned:

`Please use a minimum interval of 60 sec (please wait for 10,65625 sec).` 

Since this response is clearly not XML, the XmlReader can't do anything with it.

I'm able to successfully run your code as long as there's 60 seconds or more between connections.

A couple of things to add:

  1. Your if condition is not going to get the nodes you are looking for - XML is case-sensitive. It should be like this:

    if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "OO"))

  2. LINQ to XML would be an easier (in my mind) way of doing this:

LINQ to XML Example

using System.Xml.Linq;

// This loads the XML from the specified URI into the XDocument
XDocument xDoc = XDocument.Load("http://www.bet-at-home.com/oddxml.aspx");

// This query will return a collection of all the "OO" elements (and their children)
var oo = from x in xDoc.Descendants("OO")
         select x;

// You can iterate through this collection and do what you want
foreach (XElement ele in oo)
{
    // do something with each OO group
}

Alternatively, you could return an anonymous type (or a defined type) from the query. For example:

var oo = from x in xDoc.Descendants("OO")
         select new
         {
             Sport = x.Element("Sport").Value,
             Category = x.Element("Category").Value,
             Tournament = x.Element("Tournament").Value,
             Date = x.Element("Date").Value
             // and so on
         };

You would then have a collection of these anonymous types that you could iterate through.

If you had a class defined that you wanted to hold data in (say BettingOdds), you'd simply use that instead and the select new line would become select new BettingOdds.

Note that you'll need to check to ensure that the elements you're referring to exist, otherwise you'll get a null reference exception.

There's a ton of examples on what you can do with LINQ to XML on the internet - here's an example - LINQ To XML Tutorials with Examples

Tim
  • 28,212
  • 8
  • 63
  • 76