61

I have this as 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> 

How can I loop through all of the event:event nodes and display, for example, all of the event:SessionKey's?

This does not work:

$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

6 Answers 6

33

it does work without registerXPathNamespace and the full namespace prefix in the xpath queries:

$xml = new SimpleXMLElement($r); foreach($xml->xpath('//event:event') as $event) { var_export($event->xpath('event:sessionKey')); } 
Sign up to request clarification or add additional context in comments.

1 Comment

Yes and no, actually I consider this a bug. PHP automatically registers the namespaces of the current context. This even overrides namespaces you register yourself. You base your source on the prefixes used in the document your loading. An external source you have no control over. Prefixes that are optional, ambiguous and can change any time. Namespaces are defined, unique and stable - prefixes/aliases are not.
24

You have to register the namespace for each simpleXMLElement object you use.

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

The namespace should also be declared somewhere in the xml file.

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

The method ax described works too. You can skip the registerXPathNamespace if you know the xml file will always use the same prefix.

Comments

20

Having worked a lot with simplexml, this is how I do it.

The magic trick if you already have an element and just want to get its different namespaced children, say for a structure like this:

<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> 

Is to send TRUE as the second parameter to the children function:

 $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(); 

Comments

19

here alternative that worked for me.

$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; } 

2 Comments

The trick is using children() with at least its first parameter. If you know the document structure before hand, you can even type the namespace name (or its URI) manually as an alternative to getNamespaces().
For easier typing trick is to cast to object, ie $ns = (object) $xml->getNamespaces(true); then You could use this like $sessionKey = $skey->children($ns->event)->sessionKey;
8

Another approach is to use SimpleXML for parsing and DOMDocument for manipulation/access, which bypasses namespacing issues altogether:

$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; } 

Comments

5

Using registerXPathNamespace and then calling xpath didn't actually work for me. I had to go with the solution provided in this great post : http://blog.preinheimer.com/index.php?/archives/172-SimpleXML,-Namespaces-Hair-loss.html

So in your case, this :

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

Will output:

Learn QB in Minutes

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.