Search for and replace values in a KML file - php

I'm very new to php so go easy on me.
I'm trying to search through a KML file for latitude and longitude values, then replace them with user inputted lat/long values. The problem I'm having is actually searching through the KML file to find the specific lat/long values to be replaced.
KML:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Folder>
<name>Folder-Name</name>
<open>1</open>
<gx:Tour>
<name class="name">Tour-Name</name>
<gx:Playlist>
<gx:FlyTo>
<LookAt>
<gx:horizFov>100</gx:horizFov>
<longitude class="lookat-long">33.33333</longitude>
<latitude class="lookat-lat">-111.11111</latitude>
<altitude>0</altitude>
<heading>0</heading>
<tilt>60</tilt>
<range>100</range>
<altitudeMode>relativeToGround</altitudeMode>
</LookAt>
</gx:FlyTo>
</gx:Playlist>
</gx:Tour>
</Folder>
</kml>
I need to replace "33.33333" and "-111.11111" with user inputted values. I have tried using SimpleXML, but it does not recognize the gx: part of the tag, since that is KML specific, and not part of XML. So when I try this code:
<?php
$xml = simplexml_load_file('my_kml_file');
print_r($xml)
?>
I get this output:
SimpleXMLElement Object ( [Folder] => SimpleXMLElement Object ( [name] => Temporary Places [open] => 0 ) )
It just stops at <open> because it doesn't recognize the rest. I have spent hours upon hours trying to figure out how to best do this and I just can't. Please help.

You can use the xpath method to get the namespaced node like so:
$xml = simplexml_load_file('my_kml_file');
$xml->xpath('//gx:Tour/gx:Playlist/gx:FlyTo')[0]->LookAt->longitude = 'newValue';
$xml->xpath('//gx:Tour/gx:Playlist/gx:FlyTo')[0]->LookAt->latitude = 'newValue';
print_r($xml->asXml());
Output:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Folder>
<name>Folder-Name</name>
<open>1</open>
<gx:Tour>
<name class="name">Tour-Name</name>
<gx:Playlist>
<gx:FlyTo>
<LookAt>
<gx:horizFov>100</gx:horizFov>
<longitude class="lookat-long">newValue</longitude>
<latitude class="lookat-lat">newValue</latitude>
<altitude>0</altitude>
<heading>0</heading>
<tilt>60</tilt>
<range>100</range>
<altitudeMode>relativeToGround</altitudeMode>
</LookAt>
</gx:FlyTo>
</gx:Playlist>
</gx:Tour>
</Folder>
</kml>

Related

How to get specific tag in KML file using php DOMDocument?

I have a .kml file shaped like this :
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Document>
<name>myFile.shp</name>
<Style id="style1">
<PolyStyle>
<color>ff00ff00</color>
</PolyStyle>
</Style>
<Folder id="layer 0">
<name>background</name>
<Placemark>
<styleUrl>#style1</styleUrl>
<LineString>
<coordinates>
-2.94040373,54.83409343483 -2.943834733,54.893839393
</coordinates>
</LineString>
</Placemark>
</Folder>
</Document>
</kml>
Question
How can I get this file as a DOMDocument, and get ALL tag element with name "coordinates" ?
The goal is to be able to get the coordinates, even if the file shape change, like for example :
<kml xmlns="http://earth.google.com/kml/2.0">
<Folder>
<name>OpenLayers export</name>
<description>No description available</description>
<Placemark>
<name>OpenLayers.Feature.Vector_7341</name>
<description>No description available</description>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<coordinates>
-2.94040373,54.83409343483 -2.943834733,54.893839393
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
</Folder>
</kml>
My attempts was to loop through the document using simplexml_load_file() but unfortunately I would not be reliable as the "tag order" change between those 2 documents, and I do not know why it does not follow a single pattern (which lead me to ask this question because it may have more than 2 shape for a KML ? correct me if I am wrong).
Use DOMDocument class to parse XML. Then use getElementsByTagName() to get all coordinates elements.
$dom = new DOMDocument();
// load file
$dom->load("file.kml");
// get coordinates tag
$coordinates = $dom->getElementsByTagName("coordinates");
foreach($coordinates as $coordinate){
echo $coordinate->nodeValue;
}

Getting info from a specific XML Node

I am trying to read the value for 3 specific XML nodes (bill_codes, sent_total, clicked_unique_total) I have done a lot of testing and I feel like I need someone with fresh eyes to look at this and help me find out what I no longer see..
I am using the simplexml_load_string function to load the XML into an array..
Here is the code that I have so far:
$xml = simplexml_load_string($content);
echo $xml->methodResponse->item->responseData->message_data->message->bill_codes;
This is the XML that I am using (comes from an API Call so I have no access to modifying/updating the structure of the XML)
<?xml version="1.0" encoding="utf-8"?>
<methodResponse>
<item>
<methodName>
<![CDATA[legacy.message_stats]]>
</methodName>
<responseData>
<message_data>
<message id="2345456">
<message_subject>
<![CDATA[#1 Item You Should Be Hoarding in 2015]]>
</message_subject>
<date_sent>2014-12-18 04:01:34</date_sent>
<message_notes>
<![CDATA[Sample Notes]]>
</message_notes>
<withheld_total>0</withheld_total>
<globally_suppressed>0</globally_suppressed>
<suppressed_total>0</suppressed_total>
<bill_codes>
<![CDATA[8578]]>
</bill_codes>
<sent_total>734273</sent_total>
<link_append_statement/>
<timezone/>
<message_name>
<![CDATA[Sample Message Name]]>
</message_name>
<optout_total>4054</optout_total>
<optout_rate_total>0.55</optout_rate_total>
<clicked_total>5363</clicked_total>
<clicked_unique>4350</clicked_unique>
<clicked_rate_unique>13.71</clicked_rate_unique>
<campaign_id>228640</campaign_id>
<campaign_type>C</campaign_type>
<included_groups>
<segment id="1208891">
<![CDATA[Segment Name Here]]>
</segment>
</included_groups>
<included_smartlists></included_smartlists>
<excluded_groups></excluded_groups>
<excluded_smartlists></excluded_smartlists>
<attributes></attributes>
<link id="40278272">
<has_name>1</has_name>
<clicked_unique_total>4350</clicked_unique_total>
</link>
</message>
</message_data>
</responseData>
<responseNum>
<![CDATA[1]]>
</responseNum>
<responseCode>
<![CDATA[201]]>
</responseCode>
</item>
</methodResponse>
No need to include the parent, just start with the ->item:
echo $xml->item->responseData->message_data->message->bill_codes;
Sample Output

xpath: getting child node by searching parent attribute

I have a KML file for google maps that I want to edit. Here's a stripped-down version:
<?xml version='1.0' encoding='UTF-8'?>
<kml xmlns='http://www.opengis.net/kml/2.2'>
<Document>
<Placemark>
<name>00</name>
<snippet></snippet>
<description><![CDATA[]]></description>
<styleUrl>#Style0-polygon-3-map</styleUrl>
<ExtendedData>
<Data name='Two-Digit Districts'>
<value>AK-00</value>
</Data>
<Data name='Standard Districts'>
<value>AK-AL</value>
</Data>
<Data name='At Large as District 1'>
<value>AK-1</value>
</Data>
<Data name='Full District Name'>
<value>Alaska At Large</value>
</Data>
<Data name=''>
<value>AK</value>
</Data>
</ExtendedData>
</PlaceMark>
</Document>
</kml>
In my php code, I'm digging into each placemark node using SimpleXML:
foreach ($kml->Document->Placemark as $placemark) {
$extendeddata = $placemark->ExtendedData;
}
I need to get the <Data> node where the name attribute matches "At Large as District 1". In the XML tools plugin for NPP, when I take just the <ExtendedData>...</ExtendedData> node, this query returns the node I want: //Data[#name='At Large as District 1']. However, when I try that same query in PHP:
$targetnode = $extendeddata->xpath("//Data[#name='At Large as District 1']")
I get an empty array. I don't understand why what should be a perfectly valid xpath query isn't returning any information. Am I missing something?
There is an ending tag mismatch.
Replace </PlaceMark> with </Placemark>
Code
You have to register with a namespace in order to do an xpath in this case.
$extendeddata = simplexml_load_string( $str );
$extendeddata->registerXPathNamespace( 'ns', 'http://www.opengis.net/kml/2.2' );
$targetnode = $extendeddata->xpath("//ns:Data[#name='At Large as District 1']");
Output
Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[name] => At Large as District 1
)
[value] => AK-1
)
)
Hope this helps.

PHP newbie- specific scenario on how to parse an XML value stored in a variable using SimpleXML [duplicate]

This question already has an answer here:
php simple xml parse problem on invalid tags
(1 answer)
Closed 9 years ago.
I want to parse an XML data stored in a variable, using Simple XML.
THis is the data I am talking about:
<SearchResults:searchresults xsi:schemaLocation="http://www.zillow.com/static/xsd/SearchResults.xsd /vstatic/ae1bf8a790b67ef2e902d2bc04046f02/static/xsd/SearchResults.xsd">
<request>
<address>2114 Bigelow Ave</address>
<citystatezip>Seattle, WA</citystatezip>
</request>
<message>
<text>Request successfully processed</text>
<code>0</code>
</message>
<response>
<results>
<result>
<zpid>48749425</zpid>
<links>
<homedetails>http://www.zillow.com/homedetails/2114-Bigelow-Ave-N-Seattle-WA-98109/48749425_zpid/</homedetails>
<graphsanddata>http://www.zillow.com/homedetails/charts/48749425_zpid,1year_chartDuration/?cbt=7522682882544325802%7E9%7EY2EzX18jtvYTCel5PgJtPY1pmDDLxGDZXzsfRy49lJvCnZ4bh7Fi9w**</graphsanddata>
<mapthishome>http://www.zillow.com/homes/map/48749425_zpid/</mapthishome>
<comparables>http://www.zillow.com/homes/comps/48749425_zpid/</comparables>
</links>
<address>
<street>2114 Bigelow Ave N</street>
<zipcode>98109</zipcode>
<city>Seattle</city>
<state>WA</state>
<latitude>47.63793</latitude>
<longitude>-122.347936</longitude>
</address>
<zestimate>
<amount currency="USD">1219500</amount>
<last-updated>11/03/2009</last-updated>
<oneWeekChange deprecated="true"/>
<valueChange duration="30" currency="USD">-41500</valueChange>
<valuationRange>
<low currency="USD">1024380</low>
<high currency="USD">1378035</high>
</valuationRange>
<percentile>0</percentile>
</zestimate>
<localRealEstate>
<region id="271856" type="neighborhood" name="East Queen Anne">
<zindexValue>525,397</zindexValue>
<zindexOneYearChange>-0.144</zindexOneYearChange>
<links>
<overview>http://www.zillow.com/local-info/WA-Seattle/East-Queen-Anne/r_271856/</overview>
<forSaleByOwner>http://www.zillow.com/homes/fsbo/East-Queen-Anne-Seattle-WA/</forSaleByOwner>
<forSale>http://www.zillow.com/east-queen-anne-seattle-wa/</forSale>
</links>
</region>
<region id="16037" type="city" name="Seattle">
<zindexValue>381,764</zindexValue>
<zindexOneYearChange>-0.074</zindexOneYearChange>
<links>
<overview>http://www.zillow.com/local-info/WA-Seattle/r_16037/</overview>
<forSaleByOwner>http://www.zillow.com/homes/fsbo/Seattle-WA/</forSaleByOwner>
<forSale>http://www.zillow.com/seattle-wa/</forSale>
</links>
</region>
<region id="59" type="state" name="Washington">
<zindexValue>263,278</zindexValue>
<zindexOneYearChange>-0.066</zindexOneYearChange>
<links>
<overview>http://www.zillow.com/local-info/WA-home-value/r_59/</overview>
<forSaleByOwner>http://www.zillow.com/homes/fsbo/WA/</forSaleByOwner>
<forSale>http://www.zillow.com/wa/</forSale>
</links>
</region>
</localRealEstate>
</result>
</results>
</response>
</SearchResults:searchresults>
Now the above type of XML is stored in variable named $zillow_data
First I load it using SimpleXML using the code
$xml = simplexml_load_string($zillow_data);
Now, I want to get the "message" value as shown in the XML data above.
When I try
foreach($xml->message[0]->text[0] as $response)
It does not work.
When I try something like the below code I get an error in Netbeans IDE
foreach($xml->SearchResults:searchresults[0]->message[0]->text[0] as $response)
The error I get is "unexpected : "
How do I correctly fetch the message in above XML data?
Also how do I parse through all the "result" elements, one by one?
If You use the code:
$xml = simplexml_load_string($string);
while the $string variable contains the XML, the first element <SearchResults:searchresults> becomes the main $xml SimpleXMLElement object, while the child tags <request>, <message> and <response> are its properties.
Thus, forgetting about the undefined namespace warnings, You should be able to do e.g.:
foreach($xml->response->results->result as $result) {
echo (string) $result->zpid;
}
There is only one message with only one text element, thus if You want to echo this one, You should only do:
echo (string) $xml->message->text;
Do a var_dump($xml); to understand the XML structure being transformed into objects and arrays after loading it with SimpleXML.

Simple XML reading question (PHP)

I have the following XML file:
<?xml version="1.0" encoding="utf-8"?>
<SearchResults:searchresults xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.zillow.com/static/xsd/SearchResults.xsd /vstatic/279989c5e93d519f8d8f23d3f6cac661/static/xsd/SearchResults.xsd" xmlns:SearchResults="http://www.zillow.com/static/xsd/SearchResults.xsd">
<request>
<address>2114 Bigelow Ave</address>
<citystatezip>Seattle, WA</citystatezip>
</request>
<message>
<text>Request successfully processed</text>
<code>0</code>
</message>
<response>
<results>
<result>
<zpid>48749425</zpid>
<links>
<homedetails>http://www.zillow.com/homedetails/2114-Bigelow-Ave-N-Seattle-WA-98109/48749425_zpid/</homedetails>
<graphsanddata>http://www.zillow.com/homedetails/charts/48749425_zpid,1year_chartDuration/?cbt=3697699817560038867%7E3%7EQh4sEjEhBNEguUWA-0f22TvGUpBB7FpUkAZlBRy5_26R5PYjKDdVAA**</graphsanddata>
<mapthishome>http://www.zillow.com/homes/48749425_zpid/</mapthishome>
<myestimator>http://www.zillow.com/myestimator/Edit.htm?zprop=48749425</myestimator>
<myzestimator deprecated="true">http://www.zillow.com/myestimator/Edit.htm?zprop=48749425</myzestimator>
<comparables>http://www.zillow.com/homes/comps/48749425_zpid/</comparables>
</links>
<address>
<street>2114 Bigelow Ave N</street>
<zipcode>98109</zipcode>
<city>Seattle</city>
<state>WA</state>
<latitude>47.63793</latitude>
<longitude>-122.347936</longitude>
</address>
<zestimate>
<amount currency="USD">1112500</amount>
<last-updated>01/14/2010</last-updated>
<oneWeekChange deprecated="true"></oneWeekChange>
<valueChange duration="30" currency="USD">-77500</valueChange>
<valuationRange>
<low currency="USD">878875</low>
<high currency="USD">1145875</high>
</valuationRange>
<percentile>0</percentile>
</zestimate>
<localRealEstate>
<region id="271856" type="neighborhood" name="East Queen Anne">
<zindexValue>525,252</zindexValue>
<zindexOneYearChange>-0.104</zindexOneYearChange>
<links>
<overview>http://www.zillow.com/local-info/WA-Seattle/East-Queen-Anne/r_271856/</overview>
<forSaleByOwner>http://www.zillow.com/homes/fsbo/East-Queen-Anne-Seattle-WA/</forSaleByOwner>
<forSale>http://www.zillow.com/homes/for_sale/East-Queen-Anne-Seattle-WA/</forSale>
</links>
</region>
<region id="16037" type="city" name="Seattle">
<zindexValue>373,795</zindexValue>
<zindexOneYearChange>-0.064</zindexOneYearChange>
<links>
<overview>http://www.zillow.com/local-info/WA-Seattle/r_16037/</overview>
<forSaleByOwner>http://www.zillow.com/homes/fsbo/Seattle-WA/</forSaleByOwner>
<forSale>http://www.zillow.com/homes/for_sale/Seattle-WA/</forSale>
</links>
</region>
<region id="59" type="state" name="Washington">
<zindexValue>256,760</zindexValue>
<zindexOneYearChange>-0.074</zindexOneYearChange>
<links>
<overview>http://www.zillow.com/local-info/WA-home-value/r_59/</overview>
<forSaleByOwner>http://www.zillow.com/homes/fsbo/WA/</forSaleByOwner>
<forSale>http://www.zillow.com/homes/for_sale/WA/</forSale>
</links>
</region>
</localRealEstate>
</result>
</results>
</response>
</SearchResults:searchresults>
<!-- H:118 T:102ms S:1761 R:Fri Jan 15 10:52:49 PST 2010 B:3.0.79367-comp_rel_b -->
If you can't already tell, it's the standard output of the Zillow API. I want to store the data of information stored between certain tags, which I have learned is queried through the xpath.
For example, how would I query for the data in /SearchResults:searchresults/request/address? Doing something like this doesn't work when I echo/print the variable:
$xml = simplexml_load_file("-truncated XML URL-");
$result = $xml->xpath('/SearchResults:searchresults/request/address')
From what I understand, the $result variable should contain the value found nested in that %VALUE HERE%, correct? But it prints "Array", and when I print_r, it returns blank.
Here's a simple way to get that information:
<?php
$xml = simplexml_load_file("test.xml");
echo $xml->request->address;
?>
You need to use the full namespace not the short name.
Use http://simplepie.org
$xml = "yourxml code here";
$feed = new SimplePie();
$feed->set_raw_data($xml);
$feed->init();
$feed->handle_content_type();
echo $feed->get_adress();

Categories