Export (0) Print
Expand All

Parsing REST Services XML Responses (C#)

Bing

This tutorial shows you how to parse a Bing Maps REST Services XML request using C#.NET and XPath queries. The process is described in three steps:

  • Create the request

  • Make the request

  • Process the response

Create the basic program

Start Visual Studio and create a Visual C# Console Application project named RESTServicesXMLParseExample. Replace the content of the Program.cs files with the following sample code. Replace the placeholder insertYourBingMapsKey with your Bing Maps Key. If you do not have a Bing Maps Key, see Getting a Bing Maps Key.

using System;
using System.Xml;
using System.Xml.XPath;
using System.Net;

namespace RESTServicesXMLParseExample
{
    class Program
    {
        static string BingMapsKey = "insertYourBingMapsKey";
        static void Main(string[] args)
        {
           try
           {

                //Create the REST Services 'Find Location by Query' request
                string locationsRequest = CreateRequest("New%20York");
                XmlDocument locationsResponse = MakeRequest(locationsRequest);
                ProcessResponse(locationsResponse);
           }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.Read();
            }
        }
    }
}

Create the REST Services request

Add the following method into the Program class. This method creates a simple location query for “New York”. This type of Bing Maps REST Services Locations API request is described in Find a Location by Query.

public static string CreateRequest(string queryString)
{
    string UrlRequest = "http://dev.virtualearth.net/REST/v1/Locations/" +
                         queryString +
                         "?output=xml" +
                         " &key=" + BingMapsKey;
    return (UrlRequest);
}

Make the request

Add the following method to the Program class. This method makes a REST Services HTTP request and returns the XML response.

public static XmlDocument MakeRequest(string requestUrl)
{
    try
    {
        HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
        HttpWebResponse response = request.GetResponse() as HttpWebResponse;

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(response.GetResponseStream());
        return (xmlDoc);

    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);

        Console.Read();
        return null;
    }
}

Process the response

To process an XML response, you can use XPath queries. The following steps build a method to parse the XML response by using XPath.

Add the following method to the Program class. You will build the code for this method in the next few steps

static public void ProcessResponse(XmlDocument locationsResponse)
{
}

Create the namespace manager

To be able to retrieve data using XPath, you must create a namespace manager, add the REST Services namespace. The REST Services namespace is specified in the response. Add the following code to the ProcessResponse method to create the namespace manager.

//Create namespace manager
XmlNamespaceManager nsmgr = new XmlNamespaceManager(locationsResponse.NameTable);
nsmgr.AddNamespace("rest","http://schemas.microsoft.com/search/local/ws/rest/v1");

You are now ready to extract the information from the response. A Location that is returned in the response has the following format.

<Location>
  <Name>New York, NY</Name>
  <Point>
    <Latitude>40.714550018310547</Latitude>
    <Longitude>-74.007118225097656</Longitude>
  </Point>
  <BoundingBox>
    <SouthLatitude>40.36376953125</SouthLatitude>
    <WestLongitude>-74.745925903320312</WestLongitude>
    <NorthLatitude>41.056510925292969</NorthLatitude>
    <EastLongitude>-73.267219543457031</EastLongitude>
  </BoundingBox>
  <EntityType>PopulatedPlace</EntityType>
  <Address>
    <AdminDistrict>NY</AdminDistrict>
    <CountryRegion>United States</CountryRegion>
    <FormattedAddress>New York, NY</FormattedAddress>
    <Locality>New York</Locality>
  </Address>
  <Confidence>High</Confidence>
  <MatchCode>Good</MatchCode>
  <GeocodePoint>
    <Latitude>40.714550018310547</Latitude>
    <Longitude>-74.007118225097656</Longitude>
    <CalculationMethod>Rooftop</CalculationMethod>
    <UsageType>Display</UsageType>
  </GeocodePoint>
</Location>

The following examples show common XPath queries that you can use to get information from this Location XML response. See the links in the See Also section for more information about XPath syntax.

Get the formatted addresses

Each Location contains an Address element with a FormattedAddress.

<Location> 
  ...
  <Address>
    <AdminDistrict>NY</AdminDistrict>
    <CountryRegion>United States</CountryRegion>
    <FormattedAddress>New York, NY</FormattedAddress>
    <Locality>New York</Locality>
  </Address>
  ...
</Location>

The following options show two ways to retrieve the formatted address information.value.

Option 1

The following code uses the XPath expression “//rest:Location” to get all Location elements in the response, and then uses the XPath expression “.//rest:FormattedAddress” to get the FormattedAddress element for each Location. Insert this code after the namespace manager declaration.

//Get formatted addresses: Option 1
//Get all locations in the response and then extract the formatted address for each location
XmlNodeList locationElements = locationsResponse.SelectNodes("//rest:Location", nsmgr);
Console.WriteLine("Show all formatted addresses: Option 1"); 
foreach (XmlNode location in locationElements)
{
    Console.WriteLine(location.SelectSingleNode(".//rest:FormattedAddress", nsmgr).InnerText);
}

Option 2

The following code uses the XPath expression “//rest:FormattedAddresses” to get all FormattedAddress elements in the response.

Because there is only one FormattedAddress for each Location, this gives the same response as Option 1. However, if the Location element had more than one FormattedAddress element, and you did not want to get all of these elements, you may want to query each Location element individually as shown below. Insert this code after the previous query option.

//Get formatted addresses: Option 2
//Get all formatted addresses directly. This works because there is only one formatted address for each location.
XmlNodeList formattedAddressElements = locationsResponse.SelectNodes("//rest:FormattedAddress", nsmgr);
Console.WriteLine("Show all formatted addresses: Option 2");
foreach (XmlNode formattedAddress in formattedAddressElements)
{
    Console.WriteLine(formattedAddress.InnerText);
}

Get the geocode points to use for display

A Location element can have one or more GeocodePoints. GeocodePoints can be used for routing or display or both. The XPath expression ".//rest:GeocodePoint/rest:UsageType[.='Display']/parent::node()" gets the Geocode Points that have a UsageType of Display for each Location. Insert this code after the code to get formatted address values.

//Get the Geocode Points to use for display for each Location
XmlNodeList locationElementsForGP = locationsResponse.SelectNodes("//rest:Location", nsmgr);
Console.WriteLine("Show Geocode Point Data");
foreach (XmlNode location in locationElements)
{
    XmlNodeList displayGeocodePoints =   location.SelectNodes(".//rest:GeocodePoint/rest:UsageType[.='Display']/parent::node()", nsmgr);
    Console.WriteLine(location.SelectSingleNode(".//rest:FormattedAddress", nsmgr).InnerText);
    Console.WriteLine("Has " + displayGeocodePoints.Count.ToString() + " display geocode points");
}

Get the locations with MatchCode=Good and Confidence=High

A Location has a MatchCode and Confidence. The XPath expression "//rest:Location/rest:MatchCode[.='Good']/parent::node()" gets Locations with a MatchCode value of ‘Good’. After you retrieve these locations, you can further filter this subset of Locations to get locations that have a Confidence of High. To do this, use the XPath expression ".//rest:Confidence". Insert this code after the code to get geocode points.

//Get all locations that have a MatchCode=Good and Confidence=High
XmlNodeList matchCodeGoodElements = locationsResponse.SelectNodes("//rest:Location/rest:MatchCode[.='Good']/parent::node()", nsmgr);
Console.WriteLine("Show all addresses with MatchCode=Good and Confidence=High");
foreach (XmlNode location in matchCodeGoodElements)
{
    if (location.SelectSingleNode(".//rest:Confidence", nsmgr).InnerText == "High")
    {
        Console.WriteLine(location.SelectSingleNode(".//rest:FormattedAddress", nsmgr).InnerText);
    }
}


Run the Sample

You are now ready to run the sample code and view the results.

Complete Sample Code

The following is the complete sample code for this tutorial. This sample code uses the following REST Services Locations API request.

http://dev.virtualearth.net/REST/v1/Locations/New%20York?output=xml&key=insertYourBingMapsKey

Insert your Bing Maps Key before running this sample.

using System;
using System.Xml;
using System.Xml.XPath;
using System.Net;

namespace RESTServicesXMLParseExample
{
    class Program
    {
        static string BingMapsKey = "InsertYourBingMapsKeyHere";
        static void Main(string[] args)
        {
            try
            {

                //Create the REST Services 'Find by Query' request
                string locationsRequest = CreateRequest("New%20York");
                XmlDocument locationsResponse = MakeRequest(locationsRequest);
                ProcessResponse(locationsResponse);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.Read();
            }
        }

        //Create the request URL
        public static string CreateRequest(string queryString)
        {
             string UrlRequest = "http://dev.virtualearth.net/REST/v1/Locations/" +
                                            queryString +
                                            "?output=xml" +
                                            " &key=" + BingMapsKey;
            return (UrlRequest);
        }

        //Submit the HTTP Request and return the XML response
        public static XmlDocument MakeRequest(string requestUrl)
        {
            try
            {
                HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;

                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(response.GetResponseStream());
                return (xmlDoc);

            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);

                Console.Read();
                return null;
            }
        }

        static public void ProcessResponse(XmlDocument locationsResponse)
        {
            //Create namespace manager
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(locationsResponse.NameTable);
            nsmgr.AddNamespace("rest", "http://schemas.microsoft.com/search/local/ws/rest/v1");

            //Get formatted addresses: Option 1
            //Get all locations in the response and then extract the formatted address for each location
            XmlNodeList locationElements = locationsResponse.SelectNodes("//rest:Location", nsmgr);
            Console.WriteLine("Show all formatted addresses: Option 1");
            foreach (XmlNode location in locationElements)
            {
                Console.WriteLine(location.SelectSingleNode(".//rest:FormattedAddress", nsmgr).InnerText);
            }
            Console.WriteLine();

            //Get formatted addresses: Option 2
            //Get all formatted addresses directly. This works because there is only one formatted address for each location.
            XmlNodeList formattedAddressElements = locationsResponse.SelectNodes("//rest:FormattedAddress", nsmgr);
            Console.WriteLine("Show all formatted addresses: Option 2");
            foreach (XmlNode formattedAddress in formattedAddressElements)
            {
                Console.WriteLine(formattedAddress.InnerText);
            }
            Console.WriteLine();

            //Get the Geocode Points to use for display for each Location
            XmlNodeList locationElementsForGP = locationsResponse.SelectNodes("//rest:Location", nsmgr);
            Console.WriteLine("Show Goeocode Point Data");
            foreach (XmlNode location in locationElements)
            {
                XmlNodeList displayGeocodePoints = location.SelectNodes(".//rest:GeocodePoint/rest:UsageType[.='Display']/parent::node()", nsmgr);
                Console.Write(location.SelectSingleNode(".//rest:FormattedAddress", nsmgr).InnerText);
                Console.WriteLine(" has " + displayGeocodePoints.Count.ToString() + " display geocode point(s).");
            }
            Console.WriteLine();

            //Get all locations that have a MatchCode=Good and Confidence=High
            XmlNodeList matchCodeGoodElements = locationsResponse.SelectNodes("//rest:Location/rest:MatchCode[.='Good']/parent::node()", nsmgr);
            Console.WriteLine("Show all addresses with MatchCode=Good and Confidence=High");
            foreach (XmlNode location in matchCodeGoodElements)
            {
                if (location.SelectSingleNode(".//rest:Confidence", nsmgr).InnerText == "High")
                {
                    Console.WriteLine(location.SelectSingleNode(".//rest:FormattedAddress", nsmgr).InnerText);
                }
            }

            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }
}


Show:
© 2014 Microsoft