Parsing WMS GetCapabilities with jQuery

I’ve been thinking about adding an “anything” layer to one of my sites. By anything, I mean any layer being shared by our WMS server. There are lots of times when someone asks if they can see this or that on GeoPortal, and it just isn’t worth it/doesn’t make sense to have a dedicated layer for it in the layers list. So instead, I could have the regular layers, then down on the bottom one layer that is a drop down list with everything in a GetCapabilities response. Like so:

Sort through my drop down, shoo shoo.

Here’s how you might go about populating a drop down list from a WMS GetCapabilities document.

1
2
3
4
5
6
7
8
9
10
11
12
$.ajax({
type: "GET",
url: "http://yourserver/wms?service=wms&version=1.1.1&request=GetCapabilities",
dataType: "xml",
success: function(xml) {
$(xml).find('Layer').each(function(){
if ($(this).children("Name").text().match(/postgis:/g) != null) {
$("#wmsDirectoryLayer").append('<option value="' + $(this).children("Name").text() + '">' + $(this).children("Title").text() + '</option>');
}
});
}
});

Basically I’m grabbing the XML output. You can put in your GetCapabilities URL in here, but remember if it isn’t hosted on the same server your browser won’t allow it - you’ll need to proxy it. Then I’m getting each Layer tag, grabbing the Name and Title from it, and dropping the option into a select drop-down. The match bit is because I’m filtering for just layers from a particular namespace - you could leave that out and grab everything.

Pretty simple. Since you obviously know the WMS URL and you have the layer name, it’s a piece of cake to draw it on a map. But there’s a problem - our GetCapabilities XML response is a whopping 440kb. Even paring down the SRS capabilities to 4 projections I’m still looking at 302kb. That’s a lot to throw down the wire to the client for parsing. Instead I’ll do a little PHP on the server side to slap what I need into some JSON using PHP 5’s SimpleXML.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$url = "http://yourserver/wms?service=wms&amp;version=1.1.1&amp;request=GetCapabilities";

$str = file_get_contents($url);
$xml = simplexml_load_string( $str );


$returnArray = array();

foreach($xml->Capability->Layer->Layer as $child) {

if (strlen(strpos($child->Name, "postgis:")) > 0 ) {
array_push($returnArray, array('name' => (string)$child->Name, 'title' => (string)$child->Title));
}

}

echo json_encode($returnArray);

Beautiful. Well, as beautiful as PHP gets. Then your client-side code can look something like this, and you could include a JSONP callback to rid yourself of XSS problems:

1
2
3
4
5
6
url = "http://localhost/code/meckportal/ws_getcapabilities.php";
$.getJSON(url, function(data) {
$.each(data, function(i, item){
$("#wmsDirectoryLayer").append('<option value="' + item.name + '">' + item.title + '</option>');
});
});