Я пытаюсь найти файл KML (для тех, кто не знает, это файл XML, содержащий информацию GPS для разметки линий и многоугольников на карте), который имеет следующую структуру:
<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 МБ. Он также имеет много других папок, некоторые из которых вложены в другие папки.
Я пытаюсь получить список всех элементов 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]
Учитывая, что в этом файле у меня всего 10000 меток, я бы предпочел решение, которое не предполагает разбивки пути и нахождения типа элемента для каждой звездочки, а затем соответствующего экземпляра этого элемента внутри его родителя. Насколько я понимаю, DOMNode: getNodePath () вернет xpath, более читаемый для людей, чем их положение в родительском элементе.
Я иду по этому поводу неправильно? Есть ли лучший способ получить массив путей к моим меткам?
Приветствия.
На самом деле /XML/Document/Folder/Placemark
не будет действительным. XML использует пространство имен, поэтому вам нужно зарегистрировать префикс для него и использовать его в Xpath.
Что-то вроде /kml:XML/kml:Document/kml:Folder/kml:Placemark
,
DOMNode::getNodePath()
не имеет префикса для использования, поэтому он возвращается к *
— это соответствует любому элементу узла.
Вы можете использовать Xpath, чтобы найти необходимую информацию об узле, чтобы построить собственное выражение пути расположения. За ancestor::*
будет получать все родительские элементы до узла документа. count(preceding-sibling::Placemark)
посчитал бы все Placemark
узлы с тем же родительским узлом перед текущим.
Других решений пока нет …