我正在尝试解析这样的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 中,gml:point
但是我试图使用命名空间来达到要点,但我必须做错事,因为除了数组字之外我不能打印任何东西(即使使用print_r
...)
答案 0 :(得分:2)
您不应该从文档中读取命名空间。命名空间是一个唯一的字符串,用于定义标记所属的XML语义。您的XML就是一个很好的例子,因为它在两个不同的命名空间中有Point
个元素。
p:Point
是{http://example.org}:点
gml:Point
是{http://www.opengis.net/gml}:点
像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);
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"
}
答案 1 :(得分:0)
使用XPath会更容易,因为您的节点深度嵌套在交替的命名空间中,但由于您使用的是 SimpleXML ,我将向您展示使用该框架的解决方案。
此
$output->children($xml["p"]);
因为根节点在p
命名空间中没有 children 而无法工作。您必须在树中导航,直到您处于正确的上下文中。使用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 Fiddle 。