I\'m trying to consume the following web service http://ipinfodb.com/ip_location_api.php this web service returns an xml response, the code below gets the XML response, but
My solution would be:
run the xsd.exe
utility on your result XML twice to convert it to a XSD (first step) and a C# class (second step) - this would give you a C# class Response
next, you can easily deserialize the response into an instance of that class:
HttpWebRequest request = WebRequest.Create("http://api.ipinfodb.com/v2/ip_query.php?key=--yourkey--&ip=74.125.45.100&timezone=true") as HttpWebRequest;
XmlSerializer ser = new XmlSerializer(typeof(Response));
WebResponse response = request.GetResponse();
var result = ser.Deserialize(response.GetResponseStream());
and now your result
would contain an instance of Response
, with all the elements as nice fields in your object.
Read more about xsd.exe on its MSDN doc page.
I think you need to use _xtr.MoveToContent(); Method before using the read method.. See if that works
You are assuming that first node will be root node but that's not correct. You will have XmlDeclaration
node first and that may get followed by Whitespace
nodes. So you should probably structure your code something like
...
bool isRootRead = false;
while (_xtr.Read())
{
if (_xtr.NodeType == XmlNodeType.Element)
{
if (!isRootRead)
{
if (_xter.Name == "Response")
{
// root found
isRootRead = true;
}
// jump to next node if root node / ignore other nodes till root element is read
continue;
}
_currentField = _xtr.Name;
_xtr.Read();
if (_xtr.NodeType == XmlNodeType.Text)
{
switch (_currentField)
{
case "Status":
Console.WriteLine(_xtr.Value); //we print to console for testing purposes, normally assign it to a variable here!
break;
...
But said all that, I would personally prefer to create response XSD (better if web service provides it) and generate classes out of it (using XSD.exe or Xsd2Code) for serialize/deserialise it.
I use the this same API, I load the response XML into an XDocument and parse e.g.
// build URL up at runtime
string apiKey = ConfigurationManager.AppSettings["geoApiKey"];
string url = String.Format(ConfigurationManager.AppSettings["geoApiUrl"], apiKey, ip);
WebRequest request = WebRequest.Create(url);
try
{
WebResponse response = request.GetResponse();
using (var sr = new System.IO.StreamReader(response.GetResponseStream()))
{
XDocument xmlDoc = new XDocument();
try
{
xmlDoc = XDocument.Parse(sr.ReadToEnd());
string status = xmlDoc.Root.Element("Status").Value;
Console.WriteLine("Response status: {0}", status);
if (status == "OK")
{
// if the status is OK it's normally safe to assume the required elements
// are there. However, if you want to be safe you can always check the element
// exists before retrieving the value
Console.WriteLine(xmlDoc.Root.Element("CountryCode").Value);
Console.WriteLine(xmlDoc.Root.Element("CountryName").Value);
...
}
}
catch (Exception)
{
// handle if necessary
}
}
}
catch (WebException)
{
// handle if necessary
}
What you should also do is introduce a custom class e.g. GeoLocationInfo
and wrap your code in a function e.g. GetGeoLocation(string ip)
then instead of writing the info to the console window you can populate & return an instance of that class.