I try to find all elements <coordinates>
into kml file, but not all of them have the same structure
for example:
<Placemark>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<coordinates>
-103.6705130315019, 18.9861834531002, 312.462181927998
-103.5618913951496, 18.98673753736649, 827.0547547230755
-103.6101814498474, 19.21464825463783, 601.556189231858
-103.6705130315019, 18.9861834531002, 312.462181927998
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
And others files have other structure, for example:
<Placemark>
<MultiGeometry>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<coordinates>
-104.085929389248,19.3541278793555, 0
-104.085635763744,19.3536293022551, 0
-104.087174259165,19.3527060222406, 0
-104.087310816944,19.3536755662883, 0
-104.085929389248,19.3541278793555,0
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</MultiGeometry>
</Placemark>
I need to get all coordinates ignoring parent elements, also, some file, have one o more coordinates elements
The next code runs, but only get me one element,
foreach( $xml->getDocNamespaces(TRUE) as $strPrefix => $strNamespace ) {
if(strlen($strPrefix)==0) {
$strPrefix="a"; //Assign an arbitrary namespace prefix.
}
$xml->registerXPathNamespace($strPrefix,$strNamespace);
}
$pieces = explode(" ", $xml->xpath("//a:coordinates")[0]);
foreach ($pieces as $coordinates) {
$args = explode(",", $coordinates);
if (strlen($args[1]) != 0 ){
$coordenadas .= '{"lat": ' . $args[1] . ', "lng": ' . $args[0] . '},';
}
}
If the file have other coordinates elements, I cant get it.
2
Answers
Rather than using
SimpleXML
& it’s associated classes/methods ( which I have never used so can offer no guidance ) the task of finding all the coordinates in a KML file can be done quite easily using the nativeDOMDocument
andDOMXPath
The output from this is of the form:
I verified that this returns all coordinates with some basic counting of strings in results and original
Do not try to determinate the namespaces from prefixes in the XML document. The unique identifier of a namespace is the URI. The prefix registration is for readability. Any element node can contain namespace definitions. Namespace prefixes can change and are optional for element nodes.
The parser resolves the node name into a local name and a namespace URI. The following 3 examples can all be read as
{http://www.opengis.net/kml/2.2}kml
(Clark notation ).<kml xmlns="http://www.opengis.net/kml/2.2">
<k:kml xmlns:k="http://www.opengis.net/kml/2.2">
<keyhole:kml xmlns:keyhole="http://www.opengis.net/kml/2.2">
So just define and register your own prefix for the known namespace URI.
Basic Example:
Output:
IMPORTANT! if you use Xpath expressions on the returned SimpleXMLElement instances you will need to register on each object again.
With DOM the bootstrap is slightly more but you have an explicit
$xpath
object with the namespace registration. AlsoDOMXpath::evaluate()
supports expressions that can return scalar values directly. Also it can use callbacks from XPath into PHP.The placemark coordinates can be just a point, a simple shape or complex shapes – see https://developers.google.com/kml/documentation/kml_tut#placemarks.