PHP DOM从XML获取节点路径不返回标记名称

时间:2017-01-12 07:02:32

标签: php xml dom xpath kml

我正在尝试搜索KML文件(对于那些不知道的人来说,这是一个包含用于在地图上标记线条和多边形的GPS信息的XML文件),其布局如下:

<kml xmlns="..." blah blah blah>
    <Document id="Layers">
        <name>Layers</name>
        <Snippet></Snippet>
        <description>Sample Location Data</description>
        <Folder id="Folder1">
            <name>The First Folder</name>
            <Snippet></Snippet>
            <description>Sample Folder</description>
            <Placemark id="ID_00000">
                <name>First Placemark</name>
                <Snippet></Snippet>
                <styleUrl>#PolyStyle00</styleUrl>
                <MultiGeometry>
                    <Polygon>
                        <extrude>0</extrude>
                        <altitudeMode>clampToGround</altitude>
                        <tesselate>1</tesselate>
                        <outerBoundaryIs>
                            <LinearRing>
                                <coordinates>INSERT A TONNE OF GPS COORDINATES HERE</coordinates>
                            </LinearRing>
                        </outerBoundaryIs>
                    </Polygon>
                </MultiGeometry>
            </Placemark>
        </Folder>
    </Document>
</kml>

这只是样本数据。实际文件是15 MB。它还有更多的文件夹,其中一些嵌套在其他文件夹中。

我要做的是获取所有Placemark元素的列表。我目前的代码如下:

$data = file_get_contents(__DIR__ . './kmlFiles/lokations.kml');
$XML = new SimpleXMLElement($data);
$document = $XML->Document;
$dom = dom_import_simplexml($document);
$placemarks = $dom->getElementsByTagName('Placemark');
$placemarksArr = array();
foreach($placemarks as $dirKey => $dirVal) {
    $placemarksArr[count($placemarksArr)] = $dirVal->getNodePath();
}
var_dump($placemarksArr);

这很有效。但是,当我读完我的var_dump时,我的第一个值如下:

[0]=> string(20) "/*/*/*[4]/*[4]"

例如,下一个地标嵌套在根“目录”中第二个文件夹内的文件夹中:

[1]=> string(19) "/*/*/*[5]/*[3]/*[4]"

然而,对我而言,我期望的输出应该是:

/XML/Document/Folder/Placemark

/XML/Document/Folder[0]/Placemark[0]

鉴于我在这个文件中只有少量10,000个地标,我更倾向于一个解决方案,它不涉及我打破路径并找到每个星号的元素类型,然后在其父元素中找到该元素的相应实例。我的理解是DOMNode:getNodePath()会返回一个xpath,它比人们在父级中的位置更易读。

我是不是错了?有没有更好的方法来检索我的地标的路径数组?

干杯。

1 个答案:

答案 0 :(得分:1)

实际上/XML/Document/Folder/Placemark无效。 XML使用命名空间,因此您需要为它注册一个前缀并在Xpath中使用它。

/kml:XML/kml:Document/kml:Folder/kml:Placemark这样的东西。

DOMNode::getNodePath()没有要使用的前缀,因此它会回退到* - 它匹配任何元素节点。

您可以使用Xpath查找有关节点的必要信息,以构建您自己的位置路径表达式。对于ancestor::*,将获取文档节点之前的所有父元素。 count(preceding-sibling::Placemark)将计算当前节点之前具有相同父节点的所有Placemark个节点。