'PHP xpath query with namespaces returns broken nodes
I try to parse wfs xml structures with PHP 8.1 and have the following snippet:
<?php
$rawContent = file_get_contents('https://www.geobasisdaten.niedersachsen.de/doorman/noauth/WFS_NI_2211_ATKIS_BDLM-Modell-konform?request=getCapabilities&service=wfs&version=1.1.0');
// source: https://numis.niedersachsen.de/trefferanzeige?docuuid=e26aebd6-cc4c-4af2-8be3-8719b808df5d&plugid=/ingrid-group:iplug-csw-dsc-lgln&docid=julvu30Bh4CjFjsS0QgC
// the following works fine:
// $rawContent = file_get_contents('https://pegelonline.wsv.de/webservices/gis/aktuell/wfs?request=GetCapabilities&service=WFS&typename=gk%3Awaterlevels&version=1.1.0');
// source: https://pegelonline.wsv.de
$wfsStructure= new \SimpleXMLElement($rawContent);
$wfsStructure->registerXPathNamespace('wfs', 'http://www.opengis.net/wfs');
$wfsStructure->registerXPathNamespace('ows', 'http://www.opengis.net/ows/1.1');
$wfsStructure->registerXPathNamespace('ogc', 'http://www.opengis.net/ogc');
$resultList = $wfsStructure->xpath('//*[local-name()=\'FeatureType\']');
// same result with following xpath
// $resultList = $wfsStructure->xpath('/wfs:WFS_Capabilities/wfs:FeatureTypeList//wfs:FeatureType');
var_dump($resultList);
The result is kind of boring:
array(105) {
[0]=>
object(SimpleXMLElement)#2 (0) {
}
[1]=>
object(SimpleXMLElement)#3 (0) {
}
[2]=>
object(SimpleXMLElement)#4 (0) {
}
(…)
[103]=>
object(SimpleXMLElement)#105 (0) {
}
[104]=>
object(SimpleXMLElement)#106 (0) {
}
}
So my script detects 104 nodes, but all of them are empty. Do you have any clues why I’m stepping in trouble there? When I call the other wfs source commented in the script above, everything works fine.
Solution 1:[1]
You need a couple of tweaks - for example, $resultList = $wfsStructure->xpath('//*[local-name()=\'FeatureType\']'); doesn't work because you have a single quote sorrounding a single quote instead of a double quote).
Try it like this and see if it works. For example, to get the text values of all the <wfs:OtherSRS> nodes which are children of the 2nd <wfs:FeatureType> node:
$wfsStructure= new SimpleXMLElement($rawContent);
$wfsStructure->registerXPathNamespace('wfs', 'http://www.opengis.net/wfs');
$resultList = $wfsStructure->xpath('//wfs:FeatureTypeList//wfs:FeatureType[2]//wfs:OtherSRS');
foreach ($resultList as $result){
echo($result[0]."\n");
}
The output should be:
urn:ogc:def:crs:EPSG::25833
urn:ogc:def:crs:EPSG::3034
urn:ogc:def:crs:EPSG::3857
urn:ogc:def:crs:EPSG::4258
urn:ogc:def:crs:EPSG::4326
urn:ogc:def:crs:EPSG::900913
Solution 2:[2]
Okay, next clue I guess: The wfs file https://www.geobasisdaten.niedersachsen.de/doorman/noauth/WFS_NI_2211_ATKIS_BDLM-Modell-konform?request=getCapabilities&service=wfs&version=1.1.0 does not match the wfs schema as it has some more wfs namespaces on elements which shouldn’t have a wfs namespace.
When I remove that wfs namespaces manually before converting the file into a SimpleXMLElement, everything works fine.
$rawContent = str_replace('wfs:FeatureType', 'FeatureType', $rawContent);
$rawContent = str_replace('wfs:Name', 'Name', $rawContent);
$rawContent = str_replace('wfs:Title', 'Title', $rawContent);
But I guess, nobody should ever see this approach as I would never ever get a job again.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Jack Fleeting |
| Solution 2 | Malte |
