Si on fait:
1 2
| $sxe = simple_xml_load_file('POLEEMPLOI-Profil_Test_Physicien_v0.1.xml');
var_dump($sxe->CandidatePerson->Communication); |
On obtient:
1 2 3 4
| object(SimpleXMLElement)#4 (2) {
["ChannelCode"]=> string(5) "Email"
["UseCode"]=> string(8) "Personal"
} |
À noter qu'il n'y a aucune mention de URI ou de oa:URI qui est pourtant bien là dans le fichier xml. Pourquoi?
Parce qu'un objet simpleXMLElement ne peut accéder directement qu'aux éléments de l'espace de nom courant, aux éléments du même espace de nom que lui, pas aux autres, et donc on ne peux pas accéder à oa:URI avec les jolies petites flêflêches toutes mignonnes quand on vient d'un autre espace de nom (dans ce cas précis, l'espace de nom par défaut qui n'a pas de préfixe: http://www.hr-xml.org/3).
Donc les tentatives désespérées comme: $sxe->CandidatePerson->Communication->URI ou autres, ne marcheront pas.
Pour surmonter cette difficulté, il faut s'en remettre à l'astuce qui va guider nos pas.
1ère solution: faire une recherche en paternité.
On demande au nœud parent si par hasard il n'aurait pas des enfants dans l'espace de nom http://www.openapplications.org/oagis/9 (représenté par le préfixe oa dans le xml) en utilisant la méthode SimpleXMLElement::children:
1 2 3 4
| var_dump($sxe->CandidatePerson->Communication->children('http://www.openapplications.org/oagis/9')->URI);
// object(SimpleXMLElement)#4 (1) {
// [0]=> string(25) "lucile.dupond@yopmail.com"
// } |
2e solution: on utilise XPath en enregistrant les espaces de noms utiles à son intention.
Pour pouvoir utiliser des préfixes représentant des espaces de nom dans une requête XPath, il faut au préalable les "enregistrer" avec la méthode SimpleXMLElement::registerXPathNamespace.
Il faut également enregistrer l'espace de nom par défaut si on veut utiliser des éléments de celui-ci dans la requête puisqu'il est explicitement défini dans le xml. À noter que les préfixes choisis n'ont aucune importance, seules les URLs comptent.
1 2 3 4 5 6 7 8
| $sxe->registerXPathNamespace('ns', 'http://www.hr-xml.org/3');
$sxe->registerXPathNamespace('oa', 'http://www.openapplications.org/oagis/9');
var_dump($sxe->xpath('/ns:Candidate/ns:CandidatePerson/ns:Communication/oa:URI'));
// array(1) {
// [0]=> object(SimpleXMLElement)#2 (1) {
// [0]=> string(25) "lucile.dupond@yopmail.com"
// }
// } |
3e solution: on utilise toujours XPath, mais cette fois-ci on ignore purement et simplement les espaces de nom.
Si la vocation première des espaces de nom est d'éviter les ambiguïtés entre deux éléments de même nom mais utilisés dans des contextes ou avec des sens différents, il s'avère aussi bien souvent que ceux-ci se retrouvent de fait à n'assurer plus qu'une fonction sémantique. Autrement dit, si le document xml ne comporte pas plusieurs éléments avec le même nom dans des contextes ou avec des sens différents, on peut très bien les ignorer. Quand bien même il y en aurait, si le chemin jusqu'à un élément permet de lever l'ambiguïté, on peut se passer de leur secours.
Cette dernière solution est donc à adopter avec la précaution qui convient.
Pour ce faire on utilise * qui représente n'importe quel élément auquel on adjoint un prédicat pour vérifier le nom local de l'élément (donc sans son préfixe):
1 2 3 4 5 6
| var_dump($sxe->xpath('//*[local-name()="CandidatePerson"]/*[local-name()="Communication"]/*[local-name()="URI"]'));
// array(1) {
// [0]=> object(SimpleXMLElement)#2 (1) {
// [0]=> string(25) "lucile.dupond@yopmail.com"
// }
// } |
Ceci dit, on peut au besoin vérifier un espace de nom dans un prédicat:
*[local-name()="URI" and namespace-uri()="http://www.openapplications.org/oagis/9"]
(Dans cette perspective, la solution 2 n'est qu'un moyen d'écrire des requêtes XPath plus courtes.)
Partager