Разбор XML с именами с SimpleXMLparser php

Я пытаюсь разобрать XML следующим образом:

<?xml version="1.0" encoding="UTF-8"?> <gml:FeatureCollection xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:wfs="http://www.opengis.net/wfs" xmlns:p="http://example.org"> <gml:featureMember> <p:Point> <gml:pointProperty> <gml:Point srsName="epsg:4258"> <gml:pos>-3.84307585 43.46031547</gml:pos> </gml:Point> <gml:Point srsName="epsg:4258"> <gml:pos>-3.84299411 43.46018513</gml:pos> </gml:Point> <gml:Point srsName="epsg:4258"> <gml:pos>-3.84299935 43.45998723</gml:pos> </gml:Point> <!-- ... many more <gml:Point> nodes ... --> <gml:Point srsName="epsg:4258"> <gml:pos>-3.84309913 43.46054546</gml:pos> </gml:Point> <gml:Point srsName="epsg:4258"> <gml:pos>-3.84307585 43.46031547</gml:pos> </gml:Point> </gml:pointProperty> </p:Point> </gml:featureMember> </gml:FeatureCollection> 

Я хочу получить каждый из gml:pos строк для сохранения в БД, но на данный момент я счастлив печатать их в веб-пространстве ( echo …)

 $output = simplexml_load_string($output); $xml = $output->getNamespaces(true); //print_r( $xml); $xml_document = $output->children($xml["p"]); foreach($xml_document->Point->children($xml["gml"]); echo $xml_point->Point[0]; echo $xml->FeatureCollection; } 

В $ output у меня есть полный xml, тонны координат в gml:point

Но я пытаюсь добраться до точек с помощью пространств имен, но я должен делать что-то неправильно, потому что я не могу ничего печатать, кроме слова Array (даже с помощью print_r …)

Solutions Collecting From Web of "Разбор XML с именами с SimpleXMLparser php"

Вы не должны читать пространства имен из документа. Пространство имен – это уникальная строка, определяющая семантику XML, частью которой является тег. Ваш XML – хороший пример для этого, потому что он имеет элементы Point в двух разных пространствах имен.

p:Point { http://example.org }: Point gml:Point is { http://www.opengis.net/gml }: Point

Префиксы пространства имен, такие как p и gml являются псевдонимами, чтобы сделать документ меньшим и более читаемым. Они действительны только для элемента и его детей. Их можно переопределить в любой момент. Более важные они действительны только для документа.

Таким образом, чтобы прочитать XML, вы определяете собственные префиксы для пространств имен и используете их с помощью Xpath или используете варианты с поддержкой пространства имен DOM-методов, таких как getAttributeNS() . Xpath – это более элегантное решение. Вы можете использовать префиксы из документа или разные.

 $element = simplexml_load_string($content); $element->registerXPathNamespace('gml', 'http://www.opengis.net/gml'); $element->registerXPathNamespace('p', 'http://example.org'); $result = []; $positions = $element->xpath('//p:Point[1]//gml:pos'); foreach ($positions as $pos) { $result[] = (string)$pos; } var_dump($result); 

Выход: https://eval.in/159739

 array(5) { [0]=> string(23) "-3.84307585 43.46031547" [1]=> string(23) "-3.84299411 43.46018513" [2]=> string(23) "-3.84299935 43.45998723" [3]=> string(23) "-3.84309913 43.46054546" [4]=> string(23) "-3.84307585 43.46031547" } 

Это было бы проще с помощью XPath , поскольку у вас узлы вложены в переменные пространства имен, но поскольку вы используете SimpleXML, я покажу вам решение с использованием этой структуры.

Эта

 $output->children($xml["p"]); 

не будет работать, потому что корневой узел не имеет дочерних элементов в пространстве имен p . Вы должны перемещаться по дереву, пока не находитесь в правильном контексте. С XPath вы можете получить их все с выражением оси descendant , что было бы проще. Код ниже работает с SimpleXML :

 $pointProperty = $output ->children($xml["gml"])->featureMember ->children($xml["p"])->Point ->children($xml["gml"]); 

Теперь вы можете зациклиться на дочерних элементах pointProperty и у вас будут Point :

 foreach($pointProperty->children($xml["gml"]) as $point) print_r($point); 

Оттуда пространство имен не изменяется, поэтому вы можете нормально перемещаться и получать данные в элементах pos . Вот пример:

 echo '<table border="1">'."\n"; echo ' <tr><th>srsName</th><th>Longitude</th><th>Latitude</th></tr>'."\n"; foreach($pointProperty->children($xml["gml"]) as $point) { $coords = explode (' ', $point->pos); echo ' <tr><td>'.$point->attributes()['srsName'].'</td>'; echo '<td>'.$coords[0].'</td>'; echo '<td>'.$coords[1].'</td></tr>'."\n"; } echo '</table>'."\n"; 

Это напечатает таблицу, содержащую ваши данные. Вы можете адаптировать это в соответствии с вашими потребностями:

 <table border="1"> <tr><th>srsName</th><th>Longitude</th><th>Latitude</th></tr> <tr><td>epsg:4258</td><td>-3.84307585</td><td>43.46031547</td></tr> <tr><td>epsg:4258</td><td>-3.84299411</td><td>43.46018513</td></tr> ... <tr><td>epsg:4258</td><td>-3.84307585</td><td>43.46031547</td></tr> </table> 

Вот работающий скрипт PHP, который вы можете попробовать в Интернете.