2017-01-12 1 views
1

Ich versuche, eine KML-Datei zu durchsuchen (für diejenigen, die es nicht wissen, ist es eine XML-Datei mit GPS-Informationen zum Markieren von Linien und Polygonen auf einer Karte), das hat ein Layout wie folgt:PHP-DOM Get Node Pfad von XML gibt keine Tag-Namen zurück

<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> 

Dies ist nur Beispieldaten. Die eigentliche Datei ist 15 MB. Es hat auch viele weitere Ordner, von denen einige in anderen Ordnern verschachtelt sind.

Was ich versuche, ist eine Liste aller Placemark-Elemente zu bekommen. Mein aktueller Code sieht so aus:

$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); 

Das funktioniert. Allerdings, wenn ich durch meine Var_dump lesen, mein erster Wert ist wie folgt:

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

Die nächste Ortsmarkierung wird beispielsweise in einem Ordner innerhalb des zweiten Ordners im root „Verzeichnis“ verschachtelt:

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

Es wäre mir sinnvoll, dass der Ausgang ich erwarten würde sein sollte:

/XML/Document/Folder/Placemark 

oder

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

Da ich in dieser Datei nur knapp 10.000 Ortsmarken habe, würde ich eine Lösung bevorzugen, bei der ich den Pfad nicht aufspalte und den Elementtyp für jedes Sternchen und dann die entsprechende Instanz dieses Elements im Elternteil finde . Mein Verständnis war DOMNode: GetNodePath() würde einen Xpath besser lesbar für Menschen als ihre Position in der Eltern.

Gehe ich falsch? Gibt es eine bessere Möglichkeit, ein Array von Pfaden zu meinen Placemarks abzurufen?

Prost.

Antwort

1

Eigentlich /XML/Document/Folder/Placemark wäre nicht gültig. Der XML-Code verwendet einen Namespace, daher müssen Sie einen Präfix für ihn registrieren und ihn in Xpath verwenden.

Etwas wie /kml:XML/kml:Document/kml:Folder/kml:Placemark.

DOMNode::getNodePath() hat kein zu verwendendes Präfix, daher wird auf * zurückgegriffen - es passt zu jedem Elementknoten.

Sie können Xpath verwenden, um die erforderlichen Informationen zu einem Knoten zu finden, um einen eigenen Standortpfadausdruck zu erstellen. For ancestor::* würde alle übergeordneten Elemente bis zum Dokumentknoten abrufen. count(preceding-sibling::Placemark) würde alle Placemark Knoten mit demselben übergeordneten Knoten vor dem aktuellen Knoten zählen.

+0

Hallo, Vielen Dank für Ihre Antwort! Kann ich einen Namespace registrieren, um/XML/Dokument/Ordner/Placemark gültig zu machen, oder ist das nicht möglich? Auch von Ihrer Antwort ist mein Verständnis, dass wenn ich einen Namespace mit dem kml-Präfix hinzufügen würde, dann würde ich alle Tags ändern müssen, so dass Placemark, was ich suche, von zu Ist das richtig? Ich würde es vorziehen, dies nicht in meinen Dateien zu tun, da sie regelmäßig aktualisiert werden, aber ich denke, dass ich das in PHP machen kann.Ich werde die Dateien zwischenspeichern, um Teile zu entfernen, die ich nicht brauche, und um die Laufzeit für Clients zu verkürzen, ist die Laufzeit kein großes Problem. –

+0

Nein, Xpath 1.0 hat kein Konzept für einen Standardnamespace. Jeder Namespace muss mit einem Präfix referenziert werden. Nun, etwas wie '* [local-name() = 'tag' und namespace-uri() = 'urn: namespace']' ist möglich, aber nicht sinnvoll. Darüber hinaus können Sie Namespaces für DOM-API-Verwendung nur für Xpath-Ausdrücke nicht registrieren. Ich bin mir nicht sicher, was Sie mit dem Standortpfad trotzdem machen wollen - Sie sollten dieses Konzept vielleicht überdenken. – ThW

Verwandte Themen