У меня это как 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>
Как я могу пройти через все события: узлы событий и отображение, например, всего события: SessionKey?
Это не работает:
$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')); }
он работает без registerXPathNamespace
и полного префикса пространства имен в запросах xpath:
$xml = new SimpleXMLElement($r); foreach($xml->xpath('//event:event') as $event) { var_export($event->xpath('event:sessionKey')); }
Вы должны зарегистрировать пространство имен для каждого объекта simpleXMLElement, который используете.
$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')); }
Пространство имен также должно быть объявлено где-то в файле xml.
<event:event xmlns:event="http://www.webex.com/schemas/2002/06/service/event"> ...
Описанный метод ax также работает. Вы можете пропустить registerXPathNamespace, если знаете, что xml-файл всегда будет использовать тот же префикс.
здесь альтернатива, которая сработала для меня.
$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; }
Другой подход заключается в использовании SimpleXML
для синтаксического анализа и DOMDocument
для манипулирования / доступа, который вообще обходит проблемы с именами:
$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; }
Использование registerXPathNamespace
а затем вызов xpath
самом деле не работал для меня. Мне пришлось пойти с решением, представленным в этом замечательном посте: http://blog.preinheimer.com/index.php?/archives/172-SimpleXML,-Namespaces-Hair-loss.html
Поэтому в вашем случае это:
echo $xml->children('http://www.webex.com/schemas/2002/06/service/event')->sessionName;
Вывод:
Узнать QB в минутах
Много работая с simplexml, я так и делаю.
Волшебный трюк, если у вас уже есть элемент, и просто хочу, чтобы его разные дети с именами, скажем, для такой структуры:
<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>
Необходимо отправить true как второй параметр для функции children:
$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();
Я могу ошибаться, но я не думаю, что XML с символом двоеточия, подобным SOAP, можно корректно проанализировать с помощью SimpleXMLElement
.
Я уверен, что есть более элегантный способ сделать это, но я обычно читаю содержимое файла в переменной с помощью file_get_contents()
затем заменяю и SimpleXMLElement
двоеточия, а затем отправляю его в SimpleXMLElement
.