2009-02-27 8 views
45

J'ai ce que xml:XML Parse avec l'aide Namespace SimpleXML

<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 boucle à travers tout l'événement: nœuds d'événements et d'affichage, par exemple, tous de l'événement: SessionKey de?

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')); 
} 
+3

Cela pourrait aider http://www.lornajane.net/posts/2010/Fetching-Namespaced-XML-Elements-With-SimpleXML –

+1

* ne fonctionne pas * est et n'a jamais été une bonne description de l'erreur.PHP vous donne l'erreur suivante: * "Attention: SimpleXMLElement :: xpath(): préfixe d'espace de noms non défini" *. Si vous développez un logiciel, vous devriez écouter les avertissements de PHP. Voir aussi: [Comment obtenir des messages d'erreur utiles en PHP?] (Http://stackoverflow.com/q/845021/367456) – hakre

Répondre

-3

Je peux me tromper mais je ne pense pas que XML avec le symbole du côlon comme SOAP peut être analysé correctement à l'aide SimpleXMLElement.

Je suis sûr qu'il y a une manière plus élégante de faire ceci mais je lis habituellement le contenu de dossier dans une variable en utilisant file_get_contents() puis remplace/enlève les deux-points puis l'envoie à SimpleXMLElement.

+0

En fait, il existe un certain support pour les espaces de noms: http://us.php.net/ manual/fr/function.simplexml-element-registerXPathNamespace.php Et je suis conscient que les espaces de noms peuvent être supprimés comme suit: $ namespaceFree = preg_replace ('/ ([<< \ /]) ([a-z0- 9] +):/i ',' $ 1 $ 2 ', $ xml); Je cherche juste une meilleure solution. – user38968

+8

Folks. S'il vous plaît. N'utilisez pas d'expressions régulières ou d'autres manipulations de chaînes lorsque vous travaillez avec des données XML. Les chances de casser quelque chose (par exemple, XML "X" (pour "extensible")) sont tout simplement trop élevé. – scy

24

il fonctionne sans registerXPathNamespace et le préfixe d'espace de noms complet dans les requêtes XPath:

$xml = new SimpleXMLElement($r); 

foreach($xml->xpath('//event:event') as $event) { 
var_export($event->xpath('event:sessionKey')); 
} 
+1

Oui ça fonctionne comme un charme! –

+6

Oui et non, en fait je considère cela comme un bug. PHP enregistre automatiquement les espaces de noms du contexte actuel. Cela remplace même les espaces de noms que vous vous inscrivez. Vous basez votre source sur les préfixes utilisés dans le document de votre chargement. Une source externe sur laquelle vous n'avez aucun contrôle. Préfixes facultatifs, ambigus et pouvant changer à tout moment. Les espaces de noms sont définis, uniques et stables - les préfixes/alias ne le sont pas. – ThW

20

Vous devez vous enregistrer l'espace de noms pour chaque SimpleXMLElement vous opposeriez-vous utiliser.

$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 décrite ici fonctionne également. Vous pouvez ignorer registerXPathNamespace si vous savez que le fichier xml utilisera toujours le même préfixe.

6

Une autre approche consiste à utiliser SimpleXML pour analyse et DOMDocument pour la manipulation/accès, qui contourne complètement les problèmes d'espace 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; 
} 
11

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; 
} 
+0

L'astuce utilise 'children()' avec au moins son premier paramètre. Si vous connaissez déjà la structure du document, vous pouvez même taper manuellement le nom de l'espace de noms (ou son URI) comme alternative à 'getNamespaces()'. –

2

Après avoir beaucoup travaillé avec simplexml, voici comment je le fais.

Le tour de magie si vous avez déjà un élément et que vous voulez juste pour obtenir c'est différent des enfants d'espace de nom, par exemple pour une structure comme ceci:

<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 true comme second 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(); 
+0

Pour moi la meilleure réponse. Simple et efficace! – Grzegorz