Я пытаюсь разобрать 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
…)
Вы не должны читать пространства имен из документа. Пространство имен – это уникальная строка, определяющая семантику 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, который вы можете попробовать в Интернете.