查询多名称空间xml

时间:2016-12-14 10:32:12

标签: php xml xpath simplexml

的xml:

<lev:Locatie axisLabels="x y" srsDimension="2" srsName="epsg:28992" uomLabels="m m">
    <gml:exterior xmlns:gml="http://www.opengis.net/gml">
        <gml:LinearRing>
            <gml:posList>
            222518.0 585787.0 222837.0 585875.0 223229.0 585969.0 223949.0 586123.0 223389.0 586579.0 223305.0 586564.0 222690.0 586464.0 222706.0 586319.0 222424.0 586272.0 222287.0 586313.0 222054.0 586517.0 221988.0 586446.0 222174.0 586305.0 222164.0 586292.0 222172.0 586202.0 222232.0 586143.0 222279.0 586149.0 222358.0 586076.0 222422.0 586018.0 222518.0 585787.0
            </gml:posList>
        </gml:LinearRing>
    </gml:exterior>
</lev:Locatie>

我需要访问gml:posList。我尝试了以下

SimpleXML的:

$xmldata     = new SimpleXMLElement($xmlstr);
$xmlns       = $xmldata->getNamespaces(true);

$retval = array();

foreach( $xmldata as $attr => $child ) {
    if ( (string)$child !== '' ) {
        $retval[$attr] = (string)$child;
    }
    else {
        $retval[$attr] = $child->children( $xmlns['gml'] );
    }
}
var_export( $retval );

的xpath:

$domdoc = new DOMDocument();
$domdoc->loadXML($xml );
$xpath = new DOMXpath($domdoc);
$xpath->registerNamespace('l', $xmlns['lev'] );
$xpath->registerNamespace('g', $xmlns['gml'] );
var_export( $xml->xpath('//g:posList') );

如果我查询lev:Locatie的属性,我可以得到它们,但是,我似乎无法检索gml:posList的值或例如gml:exterior的属性。我知道我做错了什么,我只是看不出来......

1 个答案:

答案 0 :(得分:1)

您正在DOMXpath实例上注册名称空间,但使用SimpleXMLElement::xpath()调用。那样不行。您可以使用SimpleXMLElementSimpleXMLElement::registerXpathNamespace()上注册,也可以切换到DOM并使用DOMXpath::evaluate()。属性没有前缀,因此它们不在命名空间中。 gml:exterior没有任何属性,只有命名空间定义。它看起来像一个属性,但它由解析器以不同的方式处理。

关于DOMXpath::evaluate()的好处是它可以是节点列表或标量,具体取决于Xpath表达式。所以你可以直接获取一个值。

例如gml:posList

$xmlString = <<<'XML'
<lev:Locatie axisLabels="x y" srsDimension="2" srsName="epsg:28992" uomLabels="m m" xmlns:lev="urn:lev">
    <gml:exterior xmlns:gml="http://www.opengis.net/gml">
        <gml:LinearRing>
            <gml:posList>
            222518.0 585787.0 222837.0 
            </gml:posList>
        </gml:LinearRing>
    </gml:exterior>
</lev:Locatie>
XML;

$document = new DOMDocument();
$document->loadXML($xmlString);
$xpath = new DOMXpath($document);
$xpath->registerNamespace('g', 'http://www.opengis.net/gml');
var_export( 
  $xpath->evaluate('normalize-space(//g:posList)') 
);

输出:

'222518.0 585787.0 222837.0'

normalize-space()是一个Xpath函数,它用一个空格替换所有空格序列并修剪结果。因为它是一个字符串函数,所以它会从位置路径触发第一个节点的隐式转换。