I'm running PHP 5.4.14, and I'm trying to use XPath to search inside an XML document. I can't know which namespace prefix will be used for each namespace, so I define my own prefixes using registerXPathNamespace()
.
The problem is that if I register a new prefix for XPath (e.g. C
) and the document was already using it, the XPath query won't use my prefix but the original one.
Let me show you a sample code to show this behaviour:
<?php
$body = <<<EOF
<multistatus xmlns="DAV:" xmlns:VC="urn:ietf:params:xml:ns:carddav" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:C1="http://calendarserver.org/ns/">
<response>
<href>/caldav.php/jorge/contacts/</href>
<propstat>
<prop>
<current-user-principal>
<href>/caldav.php/jorge/</href>
</current-user-principal>
<resourcetype>
<collection/>
<VC:addressbook/>
</resourcetype>
<displayname/>
<VC:addressbook-home-set>
<href>/caldav.php/jorge/</href>
</VC:addressbook-home-set>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
</multistatus>
EOF;
$xml = new SimpleXMLElement($body);
$xml->registerXPathNamespace('C', 'urn:ietf:params:xml:ns:carddav');
$xpresult = $xml->xpath('//C:addressbook-home-set');
var_dump($xpresult);
If you run it you'll see the query returns no results.
Surprisingly, if I change the registered prefix from C to any other prefix that isn't already defined, such as X, then the query works as expected:
$xml->registerXPathNamespace('X', 'urn:ietf:params:xml:ns:carddav');
$xpresult = $xml->xpath('//X:addressbook-home-set');
Am I doing anything wrong? Given that I can't know what prefixes will be used in advance, is it possible to set a custom prefix and make sure it won't conflict with other prefixes in the document besides using an ugly MYPROGRAMUNUSEDPREFIXC prefix?
I know I can get the prefixes and namespaces used in the document, but I'd like to have fixed XPath query strings.
FWIW DOMXPath has this problem too (checked it).