To gain access to the OTAP XML streams you will need to e-mail the contact persons for the country in which you are interested. You will find the contact information here: http://www.itsproj.com/otap/how.html.
- There is a Java SDK for development with OTAP data but since it is pure XML you can use various coding languages. I used a VB.NET application written with Microsoft Visual Studio 2005 to receive the XML stream and perform the transformation.
- You just need a text editor to create the file for the XSL Transformation but I used Stylus Studio 2006 XML because it is a very nice and easy-to-use tool.
- You also, of course, need Bing Maps. There is an excellent interactive SDK and a reference SDK available here: http://www.microsoft.com/maps/isdk/ajax. Optionally you can download the reference SDK here: http://go.microsoft.com/?linkid=4932476.
Data Source
Let’s have a look at the data source first. We need to investigate the OTAP XML schema and the required format for the GeoRSS feed. Then we define the mapping rules for an XSLT and finally we write a small program to periodically pull and trans-form the data.
OTAP
You will find the OTAP specifications here: http://www.itsproj.com/otap/otapspec.html.
For the purposes of this article, we will concentrate only on unplanned events, but we could also retrieve current and future planned events in a similar fashion. In the screenshots below, you can see the XML tree for one incident including the data for the UK. Please note: In the UK there is currently information only for the motorways.
I am using the latitude and longitude of the framed point (the middle of the traffic incident), the description, and the estimated delay caused by this incidents.
.png)
Figure 5 Partial view of XML file representing traffic incident data, showing location and description of incident
As you can see, there is a lot more information that you could use, if necessary. For example, you could make use of the lat/long of start/end points of the incident.
.png)
Figure 6 View of XML file representing traffic incident data, showing delay time caused by incident
GeoRSS
There are various specifications for GeoRSS feeds. The Bing Map Control supports the W3C Basic Geo Vocabulary (see http://www.w3.org/2003/01/geo/). In this example, we use the WorldKit (http://worldkit.org/doc/rss.php) implementation for which we simply need a <geo:lat> and a <geo:long> tag to describe the location.
<?xml version='1.0' ?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
xmlns="http://purl.org/rss/1.0/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<item>
<title>M6 southbound between J10 and J9</title>
<description>PT10M</description>
<geo:lat>52.572115</geo:lat>
<geo:long>-2.012080</geo:long>
</item>
</rdf:RDF>
Listing 1 GeoRSS feed XML
XSL Transformation
Using Stylus Studio 2006 XML we define the mapping rules for the XSL Transformation.
.png)
Figure 7 Creating an XSLT stylesheet in Stylus Studio 2006
The XSL-file will look like this:
<?xml version='1.0' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
xmlns="http://purl.org/rss/1.0/">
<xsl:for-each select="situationPublication/situation/situationElement">
<item>
<title>
<xsl:value-of select="elementlocation/framedPoint/name/descriptor"/>
</title>
<description>
<xsl:value-of select="consequence/delay/delayTimeValue"/>
</description>
<geo:lat>
<xsl:value-of select="elementlocation/framedPoint/wgs84/latitude"/>
</geo:lat>
<geo:long>
<xsl:value-of select="elementlocation/framedPoint/wgs84/longitude"/>
</geo:long>
</item>
</xsl:for-each>
</rdf:RDF>
</xsl:template>
</xsl:stylesheet>
Listing 2 The Stylesheet to transform the data to GeoRSS
Bringing it all together
Now that we know the source OTAP-format and destination GeoRSS-format and we have defined the rules for the XSL transformation, we need to make sure that we pull the data periodically from the OTAP server and apply the transformation to it.
In Visual Studio 2005, we create a new project for a Windows Application. On the Windows Form, we add a button and two disabled text boxes.
.png)
Figure 8 Creating a Windows forms application to transform the feed
We then write code to create a WebRequest to the OTAP server and capture the response in a data stream. We use an XmlTextWriter to write the data stream to the local hard drive into the file OTAPtemp.xml.
Finally, we use the XSL file we created earlier to transform the OTAPtemp.xml file into the GeoRSS format we need and write it back to the file GeoRSS.xml. The complete process is framed by a While…Do loop so that we refresh the data every minute. You’ll find the complete code below.
Imports System
Imports System.IO
Imports System.Xml
Imports System.Xml.XPath
Imports System.Xml.Xsl
Imports System.Text
Imports System.Net
Imports System.Threading
Public Class Form1
Private inputfilename As String = "OTAPtemp.xml"
Private outputfilename As String = "GeoRSS.xml"
Private stylesheet As String = "OTAP2GeoRSS.xsl"
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim i As Integer = 0
Do Until txtStatus.Text = "Stopped"
txtStatus.Text = "Reading"
Me.Refresh()
Dim request As WebRequest = WebRequest.Create( _
"http://otap.tistrafficinfo.com/England/UnplannedEvent/content.xml")
Dim myCredentials As New NetworkCredential
myCredentials.UserName = "YOUR_USERNAME"
myCredentials.Password = "YOUR_PASSWORD"
request.Credentials = myCredentials
Dim response As WebResponse = request.GetResponse()
Dim dataStream As Stream = response.GetResponseStream()
Dim reader As New StreamReader(dataStream)
Dim responseFromServer As String = reader.ReadToEnd()
Dim OTAPWriter As New XmlTextWriter(inputfilename, Encoding.UTF8)
OTAPWriter.WriteRaw(responseFromServer)
OTAPWriter.Close()
reader.Close()
response.Close()
Dim xslt As New XslTransform
xslt.Load(stylesheet)
Dim xpathdocument As New XPathDocument(inputfilename)
Dim GeoRSSwriter As New XmlTextWriter(outputfilename, Encoding.UTF8)
GeoRSSwriter.Formatting = Formatting.Indented
xslt.Transform(xpathdocument, Nothing, GeoRSSwriter, Nothing)
GeoRSSwriter.Close()
txtStatus.Text = "Waiting"
i = i + 1
txtCycles.Text = i.ToString + " Cycles"
Me.Refresh()
Thread.Sleep(60000)
Loop
End Sub
End Class
Listing 3 VB.NET code for regularly refreshing local traffic data
Ideally, we would want to turn this process into a Windows Service and schedule it to run at intervals of our choosing. However, building a Windows Service is beyond the scope of this article.
Consuming the GeoRSS Feed in
Bing Maps
Consuming a GeoRSS feed in Bing Maps is extremely simple. You only need to make sure that the GeoRSS feed and any images you might want to use can be described by a URL. We can create a Virtual Directory in Internet Information Service Manager (IIS) MMC and point it to the directory in which our application periodically writes the GeoRSS.xml file.
We can then create a simple HTML file with the following code in order to display the data visually.
<html>
<head>
<script src="http://dev.virtualearth.net/mapcontrol/v4/mapcontrol.js"></script>
<script>
var map = null;
var layerid = 1;
function GetMap()
{
map = new VEMap('myMap');
map.LoadMap(new VELatLong(53.956, -17.5781), 7 ,'h' , false);
AddDataLayer( 'GeoRSS.xml', 'images/trafficicon.GIF' );
}
function AddDataLayer( dataSource, dataIcon )
{
var veLayerSpec = new VELayerSpecification();
veLayerSpec.Type = VELayerType.GeoRSS;
veLayerSpec.ID = layerid;
veLayerSpec.LayerSource = dataSource;
veLayerSpec.Method = 'get';
veLayerSpec.IconUrl = dataIcon;
veLayerSpec.FnCallback = onFeedLoad;
map.AddLayer(veLayerSpec);
layerid++;
}
</script>
</head>
<body onload="GetMap();">
<div id='myMap' style="position:relative; width:400px; height:400px;"></div>
</body>
</html>
Listing 4 ABing MapsBased Traffic Report
As long as our HTML page is in the same file as our GeoRSS.xml output file, then our users should see a map showing the United Kingdom, complete with all known traffic incidents.
As mentioned earlier you’ll find the complete interactive SDK as well as a reference SDK for the Bing Map Control here: http://www.microsoft.com/maps/isdk/ajax.
This article is an updated revision of an original article contributed by Johannes Kebeck. The update was performed by Robert McGovern MVP (Bing Maps/MapPoint).