2017-01-12 14 views
1

KMLファイルを検索しようとしています(知らない人は地図上に線とポリゴンをマークするためのGPS情報を含むXMLファイルです)。PHP DOM 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); 

これは機能します。

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

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

例えば次の目印を、ルート「ディレクトリ」の2番目のフォルダ内のフォルダ内にネストされています。私は私のvar_dumpて読んだときに、次のようにしかし、私の最初の値があります

それは私が期待する出力がなければならないこと、しかし、私には理にかなって:

/XML/Document/Folder/Placemark 

または

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

このファイルに10,000個目の目印を入れておけば、私はパスを分割し、すべてのアスタリスクの要素タイプを見つけて、親の中のその要素の適切なインスタンスを見つけることができます。 。私の理解はDOMNodeでした:getNodePath()は、親の中での位置よりも人間に読みやすいxpathを返します。

私はこれについて間違っていますか?目印へのパスの配列を取得するより良い方法はありますか?

乾杯。

答えて

1

実際には/XML/Document/Folder/Placemarkは無効です。 XMLは名前空間を使用するため、Xpathにプレフィックスを登録して使用する必要があります。

のようなもの/kml:XML/kml:Document/kml:Folder/kml:Placemark

DOMNode::getNodePath()には接頭辞がありませんので、*に戻ります。すべての要素ノードに一致します。

ノードの必要な情報を見つけるためにXpathを使用して、独自のロケーションパス式を構築できます。 ancestor::*の場合、すべての親要素を文書ノードまでフェッチします。 count(preceding-sibling::Placemark)は、現在のノードより前に同じ親ノードを持つノードすべてをPlacemarkと数えます。

+0

こんにちは、お返事ありがとうございます! /XML/Document/Folder/Placemarkを有効にするために名前空間を登録することはできますか、それはできませんか? また、あなたの返信から、私がkml接頭辞付きの名前空間を追加すると、Placemarkが何を探しているのかがから これは間違いありませんか?私は彼らが定期的に更新するかもしれないので、私のファイルでそれをしないことを望むだろうが、私はPHPでそれを行うことができると思います。私はファイルをキャッシュして、不要な部分を削除し、クライアントの実行時間を減らすので、ランタイムは大きな問題ではありません。 –

+0

いいえ、Xpath 1.0にはデフォルト名前空間の概念がありません。接頭辞を使用してすべての名前空間を参照する必要があります。 '* [local-name()= 'tag'やnamespace-uri()= 'urn:namespace']'のようなものは可能ですが、そのためには役に立ちません。さらに、Xpath式の場合にのみ、DOM APIの使用に名前空間を登録することはできません。とにかくロケーションパスで何をしようとしているのか分かりません。そのコンセプトを再考したいかもしれません。 – ThW

関連する問題