Использование веб-службы REST XML
Я пытаюсь использовать следующий веб-сервис http://ipinfodb.com/ip_location_api.php
эта веб-служба возвращает ответ xml, код ниже получает ответ XML, но как-то при поэтапном изменении значений из ответа XML он не работает.
Что не так с моим кодом?
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.IO;
using System.Net;
using System.Xml;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
HttpWebRequest request = null;
HttpWebResponse response = null;
String Xml;
// Create the web request
request = WebRequest.Create("http://api.ipinfodb.com/v2/ip_query.php?key=<yourkey>&ip=74.125.45.100&timezone=true") as HttpWebRequest;
// Get response
using (response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());
Xml = reader.ReadToEnd();
}
// Console xml output
Console.WriteLine(Xml); //see if we get the xml response, (YES we do)
Console.ReadLine();
string _currentField = "";
StringReader _sr = new StringReader(Xml);
XmlTextReader _xtr = new XmlTextReader(_sr);
_xtr.XmlResolver = null;
_xtr.WhitespaceHandling = WhitespaceHandling.None;
// get the root node
_xtr.Read();
if ((_xtr.NodeType == XmlNodeType.Element) && (_xtr.Name == "Response"))
{
while (_xtr.Read())
{
if ((_xtr.NodeType == XmlNodeType.Element) && (!_xtr.IsEmptyElement))
{
_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;
case "CountryCode":
Console.WriteLine(_xtr.Value);
break;
case "CountryName":
Console.WriteLine(_xtr.Value);
break;
case "RegionCode":
Console.WriteLine(_xtr.Value);
break;
case "RegionName":
Console.WriteLine(_xtr.Value);
break;
case "City":
Console.WriteLine(_xtr.Value);
break;
case "ZipPostalCode":
Console.WriteLine(_xtr.Value);
break;
case "Latitude":
Console.WriteLine(_xtr.Value);
break;
case "Longitude":
Console.WriteLine(_xtr.Value);
break;
case "Gmtoffset":
Console.WriteLine(_xtr.Value);
break;
case "Dstoffset":
Console.WriteLine(_xtr.Value);
break;
case "TimezoneName":
Console.WriteLine(_xtr.Value);
break;
case "Isdst":
Console.WriteLine(_xtr.Value);
break;
case "Ip":
Console.WriteLine(_xtr.Value);
break;
default:
// unknown field
throw new Exception("Unknown field in response.");
}
}
}
}
}
Console.ReadLine();
}
}
}
EDIT: это ответ XML, возвращенный
<?xml version="1.0" encoding="UTF-8" ?>
- <Response>
<Status>OK</Status>
<CountryCode>US</CountryCode>
<CountryName>United States</CountryName>
<RegionCode>06</RegionCode>
<RegionName>California</RegionName>
<City>Mountain View</City>
<ZipPostalCode>94043</ZipPostalCode>
<Latitude>37.4192</Latitude>
<Longitude>-122.057</Longitude>
<Gmtoffset>-28800</Gmtoffset>
<Dstoffset>0</Dstoffset>
<TimezoneName>America/Los_Angeles</TimezoneName>
<Isdst>0</Isdst>
<Ip>74.125.45.100</Ip>
</Response>
Ответы
Ответ 1
Я использую тот же API, я загружаю XML-ответ в XDocument и разбираю, например.
// 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 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
}
То, что вы также должны сделать, это ввести пользовательский класс, например. GeoLocationInfo
и заверните свой код в функцию, например. GetGeoLocation(string ip)
затем вместо того, чтобы записывать информацию в окно консоли, вы можете заполнить и вернуть экземпляр этого класса.
Ответ 2
Мое решение:
-
запустите утилиту xsd.exe
в вашем XML-примере дважды, чтобы преобразовать ее в XSD (первый шаг) и класс С# (второй шаг) - это даст вам класс С# Response
-
Далее вы можете легко десериализовать ответ в экземпляр этого класса:
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());
и теперь ваш result
будет содержать экземпляр Response
, при этом все элементы станут хорошими полями в вашем объекте.
Подробнее о xsd.exe на странице MSDN doc.
Ответ 3
Предполагается, что первый node будет root node, но это неверно. Сначала у вас будет XmlDeclaration
node, за которым последуют узлы Whitespace
. Таким образом, вы должны, вероятно, структурировать свой код как-то вроде
...
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;
...
Но сказал, что я лично предпочел бы создать ответ XSD (лучше, если веб-сервис предоставит его) и выпустить классы из него (используя XSD.exe или Xsd2Code) для сериализации/десериализации.
Ответ 4
Я думаю, вам нужно использовать _xtr.MoveToContent(); Метод перед использованием метода чтения.
Посмотрите, работает ли это