PHP中SimpleXML无法加载GML数据,如何解析为数组?
解析带命名空间的GML XML数据(PHP SimpleXML)
问题场景
有如下GML格式的XML数据:
<?xml version="1.0" encoding="utf-8" ?> <ogr:FeatureCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://ogr.maptools.org/ fire_districts.xsd" xmlns:ogr="http://ogr.maptools.org/" xmlns:gml="http://www.opengis.net/gml"> <gml:boundedBy> <gml:Box> <gml:coord><gml:X>112.921100000165</gml:X><gml:Y>-43.65832660868602</gml:Y></gml:coord> <gml:coord><gml:X>153.6407999999201</gml:X><gml:Y>-10.05939999961026</gml:Y></gml:coord> </gml:Box> </gml:boundedBy> <gml:featureMember> <ogr:IDM00007 fid="IDM00007.0"> <ogr:geometryProperty><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>153.551804332204,-28.1645084912738 153.586699999805,-28.2582999997451 153.573299999695,-28.3133 153.582500000375</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty> <ogr:AAC>NSW_FW001</ogr:AAC> <ogr:DIST_NO>1</ogr:DIST_NO> <ogr:DIST_NAME>Far North Coast</ogr:DIST_NAME> <ogr:STATE_CODE>NSW</ogr:STATE_CODE> <ogr:SOURCE>RFS</ogr:SOURCE> <ogr:GROUP_NAME xsi:nil="true"/> </ogr:IDM00007> </gml:featureMember> <gml:featureMember> <ogr:IDM00007 fid="IDM00007.1"> <ogr:geometryProperty><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>153.261225211474,-29.9401032948311 153.19820000033,-30.038899999935 153.20060000039,-30.1036999997551 153.214099999715</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty> <ogr:AAC>NSW_FW002</ogr:AAC> <ogr:DIST_NO>2</ogr:DIST_NO> <ogr:DIST_NAME>North Coast</ogr:DIST_NAME> <ogr:STATE_CODE>NSW</ogr:STATE_CODE> <ogr:SOURCE>RFS</ogr:SOURCE> <ogr:GROUP_NAME xsi:nil="true"/> </ogr:IDM00007> </gml:featureMember> </ogr:FeatureCollection>
尝试用PHP SimpleXML解析,代码如下:
<?php $data = file_get_contents("fire_districts.gml"); $xml = new SimpleXMLElement($data); $xml->registerXPathNamespace('f', 'http://ogr.maptools.org/'); $xml->registerXPathNamespace('g', 'http://www.opengis.net/gml'); $gml = $xml->xpath('/f:FeatureCollection/g:featureMember'); print_r($gml); ?>
输出结果仅显示空的SimpleXMLElement对象数组:
Array ( [0] => SimpleXMLElement Object ( ) [1] => SimpleXMLElement Object ( ) )
需要修改代码以成功将GML数据加载为数组。
解决方案
核心原因
SimpleXML在处理带命名空间的XML时,直接用print_r/var_dump不会展示命名空间内的子元素,但元素实际是存在的。需要通过指定命名空间来访问子节点,或者将其转换为普通数组。
修正代码示例
以下是完整的解析代码,可将GML数据提取为结构化数组:
<?php $data = file_get_contents("fire_districts.gml"); $xml = new SimpleXMLElement($data); // 注册命名空间 $xml->registerXPathNamespace('ogr', 'http://ogr.maptools.org/'); $xml->registerXPathNamespace('gml', 'http://www.opengis.net/gml'); // 定位所有featureMember节点 $featureMembers = $xml->xpath('/ogr:FeatureCollection/gml:featureMember'); $result = []; foreach ($featureMembers as $member) { // 获取ogr命名空间下的IDM00007节点 $district = $member->children('ogr', true)->IDM00007; $item = [ 'fid' => (string)$district['fid'], 'AAC' => (string)$district->AAC, 'DIST_NO' => (int)$district->DIST_NO, 'DIST_NAME' => (string)$district->DIST_NAME, 'STATE_CODE' => (string)$district->STATE_CODE, 'SOURCE' => (string)$district->SOURCE, 'GROUP_NAME' => isset($district->GROUP_NAME) ? (string)$district->GROUP_NAME : null, // 提取坐标数据 'coordinates' => (string)$district->geometryProperty->children('gml', true)->Polygon->outerBoundaryIs->LinearRing->coordinates ]; $result[] = $item; } print_r($result); ?>
关键说明
- 命名空间访问:使用
children('命名空间前缀', true)来访问对应命名空间下的子元素,第二个参数true表示直接使用前缀而非完整URI。 - 强制类型转换:SimpleXMLElement对象需要转换为字符串/整数等基础类型,否则会保留对象结构。
- 属性提取:通过
$element['属性名']的方式获取节点属性,同样需要强制转换为字符串。
输出示例
Array ( [0] => Array ( [fid] => IDM00007.0 [AAC] => NSW_FW001 [DIST_NO] => 1 [DIST_NAME] => Far North Coast [STATE_CODE] => NSW [SOURCE] => RFS [GROUP_NAME] => [coordinates] => 153.551804332204,-28.1645084912738 153.586699999805,-28.2582999997451 153.573299999695,-28.3133 153.582500000375 ) [1] => Array ( [fid] => IDM00007.1 [AAC] => NSW_FW002 [DIST_NO] => 2 [DIST_NAME] => North Coast [STATE_CODE] => NSW [SOURCE] => RFS [GROUP_NAME] => [coordinates] => 153.261225211474,-29.9401032948311 153.19820000033,-30.038899999935 153.20060000039,-30.1036999997551 153.214099999715 ) )
内容的提问来源于stack exchange,提问作者Mike Manning
相关产品推荐
相关产品推荐

