web-dev-qa-db-fra.com

Analyser XML avec un espace de noms à l'aide de SimpleXML

J'ai ceci au format xml:

<root xmlns:event="http://www.webex.com/schemas/2002/06/service/event">
    <event:event>
        <event:sessionKey></event:sessionKey>
        <event:sessionName>Learn QB in Minutes</event:sessionName>
        <event:sessionType>9</event:sessionType>
        <event:hostWebExID></event:hostWebExID>
        <event:startDate>02/12/2009</event:startDate>
        <event:endDate>02/12/2009</event:endDate>
        <event:timeZoneID>11</event:timeZoneID>
        <event:duration>30</event:duration>
        <event:description></event:description>
        <event:status>NOT_INPROGRESS</event:status>
        <event:panelists></event:panelists>
        <event:listStatus>PUBLIC</event:listStatus>
    </event:event>
    ...
</root>

Comment puis-je parcourir tous les nœuds d'événement: événement et afficher, par exemple, tout l'événement: SessionKey's?

Cela ne fonctionne pas:

$xml = new SimpleXMLElement($r);
$xml->registerXPathNamespace('e', 'http://www.webex.com/schemas/2002/06/service/event');

foreach($xml->xpath('//e:event') as $event) {
 var_export($event->xpath('//e:sessionKey'));
}
51
user38968

cela fonctionne sans registerXPathNamespace et le préfixe complet de l'espace de noms dans les requêtes xpath:

$xml = new SimpleXMLElement($r);

foreach($xml->xpath('//event:event') as $event) {
 var_export($event->xpath('event:sessionKey'));
}
28
ax.

Vous devez enregistrer l'espace de noms pour chaque objet simpleXMLElement que vous utilisez.

$xml = new SimpleXMLElement($r);
$xml->registerXPathNamespace('e', 'http://www.webex.com/schemas/2002/06/service/event');

foreach($xml->xpath('//e:event') as $event) {
    $event->registerXPathNamespace('e', 'http://www.webex.com/schemas/2002/06/service/event');
    var_export($event->xpath('//e:sessionKey'));
}

L'espace de noms doit également être déclaré quelque part dans le fichier xml.

<event:event xmlns:event="http://www.webex.com/schemas/2002/06/service/event">
...

La méthode hache décrite fonctionne également. Vous pouvez ignorer le registerXPathNamespace si vous savez que le fichier xml utilisera toujours le même préfixe.

21
mcrumley

ici alternative qui a fonctionné pour moi.

$xml = simplexml_load_string($r);
$ns = $xml->getNamespaces(true);

foreach ($xml->children($ns['event'])->event as $skey) {
    $sessionKey = $skey->children($ns['event'])->sessionKey;
    echo $sessionKey;
}
14
ewwink

Ayant beaucoup travaillé avec simplexml, voici comment je le fais.

L'astuce magique si vous avez déjà un élément et que vous voulez simplement obtenir ses différents enfants avec un espace de noms, disons pour une structure comme celle-ci:

<entry>
<title type="text">My test entry</title>
<Gd:when startTime="2017-02-26T02:00:00Z" endTime="2017-02-26T03:00:00Z"/>
<gc:notes type="string">A type</gc:notes>
</entry>

Est d'envoyer vrai comme deuxième paramètre à la fonction enfants:

  $title = (string) $entry->title;
  $Gd = $entry->children('Gd', TRUE);
  $attrs = $Gd->when->attributes();
  $startTime = (string) $attrs->startTime;
  $gc = $entry->children('gc', TRUE);
  $notes = (string) $gc->notes();
12
Cameron

Une autre approche consiste à utiliser SimpleXML pour l'analyse et DOMDocument pour la manipulation/l'accès, qui contourne complètement les problèmes d'espaces de noms:

$xml = new SimpleXMLElement($r);
$xml = dom_import_simplexml($xml);
$nodelist= $xml->getElementsByTagName('event');  
for($i = 0; $i < $nodelist->length; $i++) {
    $sessions = $nodelist->item($i)->getElementsByTagName('sessionKey');
    echo $sessions->item(0)->nodeValue;
}
6
Asad Saeeduddin

Utiliser registerXPathNamespace puis appeler xpath ne fonctionnait pas vraiment pour moi. Je devais aller avec la solution fournie dans ce super article: http://blog.preinheimer.com/index.php?/archives/172-SimpleXML,-Namespaces-Hair-loss.html

Donc dans votre cas, ceci:

echo $xml->children('http://www.webex.com/schemas/2002/06/service/event')->sessionName;

Sortira:

Apprenez QB en quelques minutes

4
Raf