Разбор XML с пространством имен с использованием SimpleXML - PullRequest
51 голосов
/ 27 февраля 2009

У меня есть это как 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's?

Это не работает:

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

Ответы [ 7 ]

28 голосов
/ 07 марта 2009

работает без registerXPathNamespace и полного префикса пространства имен в запросах xpath:

$xml = new SimpleXMLElement($r);

foreach($xml->xpath('//event:event') as $event) {
 var_export($event->xpath('event:sessionKey'));
}
21 голосов
/ 11 марта 2009

Вы должны зарегистрировать пространство имен для каждого используемого вами объекта 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">
...

Описанный метод топора тоже работает. Вы можете пропустить registerXPathNamespace, если знаете, что xml-файл всегда будет использовать один и тот же префикс.

13 голосов
/ 05 февраля 2014

вот альтернатива, которая у меня сработала.

$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;
}
10 голосов
/ 26 февраля 2017

Много поработав с 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 в качестве второго параметра для дочерней функции:

  $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();
6 голосов
/ 30 ноября 2012

Другой подход заключается в использовании 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;
}
4 голосов
/ 21 марта 2012

Использование 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 за минуты

0 голосов
/ 28 февраля 2009

Я могу ошибаться, но я не думаю, что XML с символом двоеточия, таким как SOAP, можно правильно проанализировать с помощью SimpleXMLElement.

Я уверен, что есть более элегантный способ сделать это, но я обычно читаю содержимое файла в переменную, используя file_get_contents(), затем заменяю / удаляю двоеточия и отправляю его на SimpleXMLElement.

...