Left on the Web

More namespace gotchas

Earlier on I had a problem with namespaces for getting XML attributes. When I finally got that sorted, I ran into an even weirder problem when fetching elements using xpath. Again, it was just a tiny little detail.

My problem with the elements was the opposite of my earlier problem. I was trying to fetch elements that were not namespaced, or so I thought. I had overlooked the fact that there was a default namespace with no prefix in the document.

It took me a while to find the fact that there was a global namespace, but even that didn't solve the problem. First, I tried simply getting all namespaces and registering them for Xpath:

$namespaces = $text->getNamespaces ( true );
foreach ( $namespaces as $prefix => $namespace ) {
    $text->registerXpathNamespace ( $prefix, $namespace );
}

I thought this should solve the problem, but it didn't. I still didn't get anything back from my Xpath query.

A lot of Googling later, it turned out there is this weird thing with default namespaces. Xpath just can't handle it without prefix. This article pushed me in the right direction. It's on DOM and only slightly mentions SimpleXML, but indeed, it's the same in XML. So what's the solution?

$namespaces = $text->getNamespaces ( true );
foreach ( $namespaces as $prefix => $namespace ) {
    if (empty ( $prefix )) {
        $prefix = 'default';
    }
    $text->registerXpathNamespace ( $prefix, $namespace );
}

Simple as that. Just check for the empty prefix, fill it, and things will start working. Don't forget to use your prefix in your Xpath query as well!

$links = $text->xpath ( '//default:a' );

These are the kinds of things that you encounter once and then always remember, so encounter them here by reading lest you not fall into the same pit ;)


Add comment
© 2004 - 2008 Stefan Koopmanschap + Powered by Symfony, photos powered by Flickr, links powered by Ma.gnolia, Shanghai smilies by Iconbuffet. Feeds: rss / atom. Left on the Web v4.2.2