This website recently got a major rebuild; if you're missing something, let Lorna know.

Fetching Namespaced XML Elements With SimpleXML



Recently I was working with some google APIs and needed to retrieve some namespaced elements from the result set. This confused me more than I expected it to so here's my code for the next time I need it (and if you use it too, then great!)

I was reading from their analytics data feed API, this returns a few key fields and then multiple <entry> tags, each with namespaced children. The entry tags look something like:

http://www.google.com/analytics/feeds/data?ids=ga:578671&ga:date=20101005&start-date=2010-10-01&end-date=2010-10-10
2010-10-09T17:00:00.001-07:00
ga:date=20101005

While you can access the non-namespaced elements either by addressing them directly or by iterating over the parent, the namespaced ones remain determinedly invisible, until you call asXML() on the node again. However we can retrieve them easily if we specify their namespace.

Retrieving Namespaces

When I get the response from my request to the API, I simply load the resulting string as a SimpleXMLElement. To get the namespaces, I simply call:

$namespaces = $xml->getNamespaces(true);
And I get an array with prefixes and full URLS, looking something like this:
Array
(
[] => http://www.w3.org/2005/Atom
[gd] => http://schemas.google.com/g/2005
[openSearch] => http://a9.com/-/spec/opensearch/1.1/
[dxp] => http://schemas.google.com/analytics/2009
)

Retrieving Namespaced Elements

We can use the array we found from getNamespaces() to make it easier to find the elements we are interested in - instead of specifying the URLs, we can just refer to the prefix we see in the raw XML. So for me to fetch those dxp: namespaced elements, I can take my entry node (called $entry in this example) and fetch them by passing the namespace I want to children().

foreach($entry->children($namespaces['dxp']) as $child) {
  // now do your Cool Stuff (TM)
}

I was confused at first because I expected to be able to do this from the top level, or to refer to elements directly by name, since I can see perfectly well what they are called in the XML! However it seems like this is the best way to approach this - iterating over children from this namespace.

Comments, suggestions and improvements all gratefully received.


In: php
Tags: #analytics #api #google #php #simplexml #xml