My first attempt at retrieving data from XML for a maps application has failed. Here is a piece of the XML Feed.
<?xml version="1.0" encoding="UTF-8"?>
<DirectionsResponse>
<status>OK</status>
<route>
<leg>
<start_address>Winkfield, Bracknell, Berkshire RG42 6LY, UK</start_address>
<end_address>Wentworth, Surrey GU25 4, UK</end_address>
</leg>
</route>
</DirectionsResponse>
I want to get the start and end address and return them via AJAX to the application.
The PHP
<?php
$start = $_POST['start'];
$end = $_POST['end'];
$xml = simplexml_load_file('http://maps.googleapis.com/maps/api/directions/xml?origin='.$start.'&destination='.$end.'&sensor=false');
// data to fetch
$start = $xml->xpath("/DirectionsResponse/route/leg/start_address");
$end = $xml->xpath("/DirectionsResponse/route/leg/end_address");
$start = array($start);
// output
echo json_encode( array('output'=>$start[0]));
?>
Annoyingly this is returning an object to the page.
Response :: {"output":[{"0":"Winkfield, Windsor, Berkshire SL4 2ES, UK"}]}
Anyone know how to stop that from happening. I just want the value Winkfield, Windsor, Berkshire SL4 2ES, UK.
Haven't tested your specific case, but i remember running into something similar when using SimpleXML, you might want to use (string) to cast it out of the object
array('output'=> (string)$start[0])
Or rather just leave out $start = array($start) and just do
array('output'=> (string)$start)
On reading the SimpleXML XPath documentation (http://www.php.net/manual/en/simplexmlelement.xpath.php) again i think your problem might be this:
Returns an array of SimpleXMLElement objects or FALSE in case of an error.
So the XPath returns an array, then you wrap that in an array and take the first element of that array, so all you end up with is the original array - remove the array wrap and you should be fine
function XMLReader()
{
$MyArray = array();
$doc = new DOMDocument();
$doc->load( 'XMLFilePath.xml' );
$info = $doc->getElementsByTagName( "leg" );
foreach( $info as $Type )
{
$details = $Type->getElementsByTagName( "start_address" );
$detail = $details->item(0)->nodeValue;
$MyArray [] = $detail;
}
return $MyArray;
}
and same for end_Address.
I wish this answer is helpful.
Just echo $start? Also, why do you make an array of start and then output the first element, it doesnt make any sense at all.
echo $xml->route->leg->start_address;
This is the edited answer. I checked it. Its working properly on the XML.
Related
I have a remote XML file. I need to read, find some values an save them in an array.
I've got load the file with (no problem with this):
$xml_external_path = 'http://example.com/my-file.xml';
$xml = file_get_contents($xml_external_path);
In this file there are many instances of:
<unico>4241</unico>
<unico>234</unico>
<unico>534534</unico>
<unico>2345334</unico>
I need to extract just the number of these strings and save them in a array. I guess I need to use a pattern like:
$pattern = '/<unico>(.*?)<\/unico>/';
But I'm not sure what to do next. Keep in mind that it is an .xml file.
Result should be a populated array like this:
$my_array = array (4241, 234, 534534,2345334);
You can better use XPath to read through an XML file. XPath is a variant of DOMDocument focused on reading and editing XML files. You can query an XPath variable using patterns, which is based on the simple Unix path syntax. So // means anywhere and ./ means relative to selected node. XPath->query() will return a DOMNodelist with all the nodes according to the pattern. The following code will do what you want:
$xmlFile = "
<unico>4241</unico>
<unico>234</unico>
<unico>534534</unico>
<unico>2345334</unico>";
$xmlDoc = new DOMDocument();
$xmlDoc->loadXML($xmlFile);
$xpath = new DOMXPath($xmlDoc);
// This code returns a DOMNodeList of all nodes with the unico tags in the file.
$unicos = $xpath->query("//unico");
//This returns an integer of how many nodes were found that matched the pattern
echo $unicos->length;
You can find more info on XPath and its syntax here: XPath on Wikipedia#syntax
DOMNodeList implements Traversable, so you can use foreach() to traverse it. If you really want a flat array you can simply convert is using simple code like in question #15807314:
$unicosArr = array();
foreach($unicos as $node){
$unicosArr[] = $node->nodeValue;
}
Using preg_match_all:
<?php
$xml = '<unico>4241</unico>
<unico>234</unico>
<unico>534534</unico>
<unico>2345334</unico>';
$pattern = '/<unico>(.*?)<\/unico>/';
preg_match_all($pattern,$xml,$result);
print_r($result[0]);
You could try this, it basically just loops through each line of the file and finds whatever is between the XML <unico> tags.
<?php
$file = "./your.xml";
$pattern = '/<unico>(.*?)<\/unico>/';
$allVars = array();
$currentFile = fopen($file, "r");
if ($currentFile) {
// Read through file
while (!feof($currentFile)) {
$m_sLine = fgets($currentFile);
// Check for sitename validity
if (preg_match($pattern, $m_sLine) == true) {
$curVar = explode("<unico>", $m_sLine);
$curVar = explode("</unico>", $curVar[1]);
$allVars[] = $curVar[0];
}
}
}
fclose($currentFile);
print_r($allVars);
Is this sort of what you want? :)
I am trying to search for a php variable in an xml file using xpath, but failing miserably. It works with a hard coded value, so I am nearly there..
<visitors>
<detail>
<id>876867</id>
<name>Bob McHaggis</name>
<email>bob#gmail.com</email>
</detail>
<detail>
<id>897987</id>
<name>Mark McBob</name>
<email>mark#gmail.com</email>
</detail>
</visitors>
<?php $sxe = simplexml_load_file("/CaptivePortal/visitors.xml");
foreach($sxe->xpath('//visitors/detail') as $item){
$row = simplexml_load_string($item->asXML());
$v = $row->xpath('//id[. ="'.$_COOKIE["judsons"].'"]');
} echo $v[0]; ?>
This works great checks for an id against the id stored in the cookie. But based on that value being found how do I access the name and email for the key matched?
Found & matched: 897987
I want to echo the name and email to, so based on that is Mark McBob & mark#gmail.com
My initial advice would be to take a good few minutes to (re-)read through the SimpleXML Basic Usage page in the PHP manual.
For selecting a single item within the XML file, there is no need at all to loop over anything. The example code below, and why it is different from yours, should become clear after familiarising yourself with the page mentioned above.
<?php
$search_id = (int) $_COOKIE["judsons"];
$visitors = simplexml_load_file("/CaptivePortal/visitors.xml");
$details = $visitors->xpath("detail[id='$search_id']");
if (empty($details)) {
echo "No details found for '$search_id'.";
} else {
$detail = $details[0];
$name = (string) $detail->name;
$email = (string) $detail->email;
echo "$name's email is $email";
}
The idea above is that $details will be an array containing hopefully just one <detail> element. It could be an empty array if no <detail> was found with the specified <id>, which is what the if(empty(…)) checks for. If the $details array is not empty, we're really only interested in the first one ($details[0]).
To access the information available within the <detail>, as explained on the "basic usage" page, the elements can be accessed with normal object property syntax ($detail->name). Doing so returns an object for that item (e.g. the <name>), so to get at the value as a string the object is type cast using (string).
You're actually doing quite a bit you don't need to there. For one thing, you don't need the loop. For another, inside your loop, you convert the context XML into a string (::asXML()), then convert it back into XML (simplexml_load_string()).
All you need is:
$xml = "<visitors><detail><id>876867</id><name>Bob McHaggis</name><email>bob#gmail.com</email></detail><detail><id>897987</id><name>Mark McBob</name><email>mark#gmail.com</email></detail></visitors>";
$sxe = simplexml_load_string($xml);
$row = $sxe->xpath('detail[id = '.$_COOKIE["judsons"].']');
That gets you the row. To extract part of it:
$name = $row[0]->xpath('name');
echo $name[0]; //Mark McBob
I'm fairly new to php although I've been programming for a couple years.
I'm working on a project and the end goal is to load certain elements of an xml file into an oracle table on a nightly basis. I have a script which runs nightly and saves a the file on my local machine. I've searched endlessly for answers but have been unsuccessful.
Here is an aggregated example of the xml file.
<?xml version="1.0" encoding="UTF-8" ?>
<Report account="7869" start_time="2012-02-23T00:00:00+00:00" end_time="2012-02-23T15:27:59+00:00" user="twilson" more_sessions="false">
<Session id="ID742247692" realTimeID="4306650378">
<Visitor id="5390643113837">
<ip>128.XXX.XX.XX</ip>
<agent>MSIE 8.0</agent>
</Visitor>
</Session>
<Session id="ID742247695" realTimeID="4306650379">
<Visitor id="7110455516320">
<ip>173.XX.XX.XXX</ip>
<agent>Chrome 17.0.963.56</agent>
</Visitor>
</Session>
</Report>
One thing to note is that the xml file will contain several objects which I will need to load into my table and the above example would just be for two rows of data. I'm familiar with the whole process of connecting and loading data into oracle and have setup similar scripts which perform ETL of txt. and csv. files using php. Unfortunately for me in this case the data is stored in xml. The approach I've taken when loading a csv. file is to load the data into an array and proceed from there.
I'm pretty certain that I can use something similar and perhaps create variable for each or something similar but am not really too sure how to do that with an xml. file.
$xml = simplexml_load_file('C:/Dev/report.xml');
echo $xml->Report->Session->Visitor->agent;
In the above code i'm trying to just return the agent associated with each visitor. This returns an error 'Trying to get property of non-object in C:\PHP\chatTest.php on line 11'
The end result would be for me to load the data into a table similar to the example I provided would be to load two rows into my table which would look similar to below however I think I can handle that if i'm able to get the data into an array or something similar.
IP|AGENT
128.XXX.XX.XX MSIE 8.0
173.XX.XX.XXX Chrome 17.0.963.56
Any help would be greatly appreciated.
Revised Code:
$doc = new DOMDocument();
$doc->load( 'C:/Dev/report.xml' );
$sessions = $doc->getElementsByTagName( "Session" );
foreach( $sessions as $session )
{
$visitors = $session->getElementsByTagName( "Visitor" );
foreach( $visitors as $visitor )
$sessionid = $session->getAttribute( 'realTimeID' );
{
$ips = $visitor->getElementsByTagName( "ip" );
$ip = $ips->item(0)->nodeValue;
$agents = $visitor->getElementsByTagName( "agent" );
$agent = $ips->item(0)->nodeValue;
echo "$sessionid- $ip- $agent\n";
}}
?>
The -> operator in PHP means that you are trying to invoke a field or method on an object. Since Report is not a method within $xml, you are receiving the error that you are trying to invoke a property on a non-object.
You can try something like this (don't know if it works, didn't test it and haven't written PHP for a long time, but you can google it):
$doc = new DOMDocument();
$doc->loadXML($content);
foreach ($doc->getElementsByTagName('Session') as $node)
{
$agent = $node->getElementsByTagName('Visitor')->item(0)->getElementsByTagName('agent')->item(0)->nodeValue;
}
edit:
Adding stuff to an array in PHP is easy as this:
$arr = array();
$arr[] = "some data";
$arr[] = "some more data";
The PHP arrays should be seen as a list, since they can be resized on the fly.
I was able to figure this out using simplexml_load_file rather than the DOM approach. Although DOM works after modifying the Leon's suggestion the approach below is what I would suggest.
$xml_object = simplexml_load_file('C:/Dev/report.xml');
foreach($xml_object->Session as $session) {
foreach($session->Visitor as $visitor) {
$ip = $visitor->ip;
$agent = $visitor->agent;
}
echo $ip.','.$agent."\n";
}
I am trying to retrieve data from this XML style file :
<Product_Group>
<Product_Group_ID>131</Product_Group_ID>
<Product_Group_Title>Thanks for the Memories</Product_Group_Title>
<Products>
<On_Sale_Date>03/01/12 00:00:00.000</On_Sale_Date>
<ISBN>9780007233694</ISBN>
<Title>Thanks for the Memories</Title>
<Format>Paperback</Format>
<Sub_Format/>
<CoverImageURL_Small>http://www.harpercollins.com/harperimages/isbn/small/4/9780007233694.jpg</CoverImageURL_Small>
</Products>
</Product_Group>
I am using following code but this seems to retrieve nothing. any help in fixing this issues would be highly appreciated
$xml = simplexml_load_string($response);
//$xml= $response;
$updates = array();
//loop through all the entry(s) in the feed
for ($i=0; $i<count($xml->Product_Group); $i++)
{
//get the id from entry
$ISBN = $xml->entry[$i]->ISBN;
//get the account link
$Title = $xml->entry[$i]->Title;
//get the tweet
$Product_Group_SEO_Copy = $xml->entry[$i]->Product_Group_SEO_Copy;
}
1) It is not valid XML. What warnings do you see? You'll need to fix them for simplexml_load_string to work properly.
For example, </CoverImageURL_Small> should be <CoverImageURL_Small/>
2) Assuming that Product_Group is not your actual document root (if it is than $xml points to it already and $xml->Product_Group will not work) then you can access each element like
$xml->Product_Group->Products[$i]->ISBN;
3) It's usually simpler to use a foreach loop than a for loop when dealing with simplexml
foreach($xml->Product_Group->Products as $p)
{
$ISBN = $p->ISBN;
//var_dump($ISBN);
}
I am trying to read the attributes of the first tag of an XML.
Here's the XML structure
<myxml timestamp="1301467801">
<tag1>value1</tag1>
<tag2>value2</tag2>
…
</myxml>
And here's how I try to get the timestamp attribute (tried 2 approaches, listing them both here, none works)
$timestamp = $xml->myxml->attributes()->timestamp; //gives Node no longer exists warning
if($xml->myxml && $xml->myxml->attributes()){ //Doesn't enter this loop
$arr = $xml->myxml->attributes();
$timestamp = $arr['timestamp'];
}
Can someone please let me know how I can get the attribute's value? Thanks.
It's because your $xml actually points to the root element. Correct usage would be:
$timestamp = $xml->attributes()->timestamp;
The right way to access attributes [as long as they belong to the node's namespace] is to use the array notation. Reserve attributes for namespaced attributes.
Also, you should name the variable that represent your XML document after its root node. It's a good practice that prevents many mixups.
$myxml = simplexml_load_string(
'<myxml timestamp="1301467801">
<tag1>value1</tag1>
<tag2>value2</tag2>
</myxml>'
);
echo $myxml['timestamp'];
<?php
$myxml = simplexml_load_string(
'<myxml timestamp="1301467801">
<tag1>value1</tag1>
<tag2>value2</tag2>
</myxml>'
);
$test = $myxml['timestamp'];
// will asign simpleXMLElement
echo $test; // -> will print nothing
// you need to cast the simpleXMLElement attribute as STRING!!!
$test = (string)$myxml['timestamp'];
echo $test;
?>