query xpath with php - php

I wrote following php code to extract nodes information from this xml:
<sioctBoardPost rdfabout="http//boards.ie/vbulletin/showpost.php?p=67075">
<rdftype rdfresource="http//rdfs.org/sioc/ns#Post" />
<dctitle>hib team</dctitle>
<siochas_creator>
<siocUser rdfabout="http//boards.ie/vbulletin/member.php?u=497#user">
<rdfsseeAlso rdfresource="http//boards.ie/vbulletin/sioc.php?sioc_type=user&sioc_id=497" />
</siocUser>
</siochas_creator>
<dctermscreated>1998-04-25T213200Z</dctermscreated>
<sioccontent>zero, those players that are trialing 300 -400 pingers? umm..mager lagg and even worse/</sioccontent>
</sioctBoardPost>
<?php
$xml = simplexml_load_file("boards.xml");
$products[0] = $xml->xpath("/sioctBoardPost/sioccontent");
$products[1] = $xml->xpath("/sioctBoardPost/dctermscreated");
$products[2] = $xml->xpath("/sioctBoardPost/#rdfabout");
print_r($products);
?>
This gives following output:
Array (
[0] => Array ( [0] => SimpleXMLElement Object ( [0] => zero, those players that are trialing for hib team, (hpb's) most of them are like 300 -400 pingers? umm..mager lagg and even worse when they play on uk server's i bet/ ) ) [1] => Array ( [0] => SimpleXMLElement Object ( [0] => 1998-04-25T213200Z ) ) [2] => Array ( [0] => SimpleXMLElement Object ( [#attributes] => Array ( [rdfabout] => http//boards.ie/vbulletin/showpost.php?p=67075 ) ) )
)
But I need only nodes content as an output i.e without Array([0] => Array etc.
Output should be like this:
zero, those players that are trialing for hib team, (hpb's) most of them are like 300 -400 pingers? umm..mager lagg and even worse when they play on uk server's i bet
1998-04-25T213200Z
http//boards.ie/vbulletin/showpost.php?p=67075
Thanks in advance

You can use current() to only get the first element of each XPath result (which is an array) and then use a (string) cast to get the node contents:
$products[0] = (string)current($xml->xpath("/sioctBoardPost/sioccontent"));
$products[1] = (string)current($xml->xpath("/sioctBoardPost/dctermscreated"));
$products[2] = (string)current($xml->xpath("/sioctBoardPost/#rdfabout"));
print_r($products);

As you have observed, the xpath() method returns an array of matched nodes, so you need to deal with the elements of the returned arrays. I believe this should work in this case:
$xml = simplexml_load_file("boards.xml");
$products[0] = $xml->xpath("/sioctBoardPost/sioccontent")[0];
$products[1] = $xml->xpath("/sioctBoardPost/dctermscreated")[0];
$products[2] = $xml->xpath("/sioctBoardPost/#rdfabout")[0];
print_r($products);

This should get you what you need...
foreach ($products as $product) { // iterate through the $products array
print $product[0]->nodeValue // output the node value of the SimpleXMLElement Object
}

Related

foreach loop, if this result is same as the last, skip to next that is not the same

i am running a foreach loop to get data from an xml file. the xml file has the same date listed several times, each with different data. what i need to do is show each date only once.
basicly i need the foreach loop to show the first date (object) on the first loop. if the date (object) is the same on the second, third, fourth loop, etc. then skip that loop and move to the next where the date (object) is not the same.
here is what i have now:
$dateResults = $xml->xpath('/rtnshowtime/filmtitle/show[preceding-sibling::shortname="AGOODDAYTODIEHARD"]');
foreach ($dateResults as $dateResult) {
print_r($dateResult->date);
echo "<br>";
}
that produces:
SimpleXMLElement Object ( [0] => 02152013 )
SimpleXMLElement Object ( [0] => 02152013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02152013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02162013 )
SimpleXMLElement Object ( [0] => 02162013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02162013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02162013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02162013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02172013 )
SimpleXMLElement Object ( [0] => 02172013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02172013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02172013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02172013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02182013 )
SimpleXMLElement Object ( [0] => 02182013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02192013 )
SimpleXMLElement Object ( [0] => 02192013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02202013 )
SimpleXMLElement Object ( [0] => 02202013 ) <-- this one needs to be skipped
SimpleXMLElement Object ( [0] => 02212013 )
SimpleXMLElement Object ( [0] => 02212013 ) <-- this one needs to be skipped
You could try something like putting the date as key and check to see if the date has already been used.
$dateResults = $xml->xpath('/rtnshowtime/filmtitle/show[preceding-sibling::shortname="AGOODDAYTODIEHARD"]');
$finalResults = array();
foreach ($dateResults as $dateResult) {
// change your simplexml object to either (int) or (string)
$date = (int) $dateResult->date;
// checks key for repeating date
if (!array_key_exists($date, $finalResults)){
// assuming you want the entire $dateResult match with date as key
$finalResults[$date] = $dateResult
}
}
// to print out the results
foreach ( $finalResult as $result ){
foreach ( $results as $key => $value ){
echo $key." : ".$value;
}
}
// or if you know the date and what you want from that array
echo (string) $finalResult[2152013]['salelink']
Untested, please let me know if theres something not working.
You could add the dates into an array and then check for existence during the loop:
// create array for storing unique dates
$unique_dates = array();
$dateResults = $xml->xpath('/rtnshowtime/filmtitle/show[preceding-sibling::shortname="AGOODDAYTODIEHARD"]');
foreach ($dateResults as $dateResult)
{
// need this to get the time attribute from the object
$time_index = 0;
// if the date does not exist in unique dates array
if ( ! in_array($dateResult->date->$time_index, $unique_dates))
{
// add to unique dates array
$unique_dates[] = $dateResult->date->$time_index;
print_r($dateResult->date);
echo "<br>";
}
}
ok, here's what i have opted for.
$shortname = $_GET['shortname'];
$dateURL = $_GET['date'];
$use_errors = libxml_use_internal_errors(true);
$xml = simplexml_load_file('XML/showtimes.xml');
if (!$xml) {echo "NO XML loaded<br>";}else{echo "XML IS loaded<br>";}
$results = $xml->xpath('/rtnshowtime/filmtitle[child::shortname="'.$shortname.'"]');
foreach ($results as $result) {
echo "showtimes for ".$dateURL."<br>";
foreach ($result->show as $result2) {
if ($result2->date == $dateURL) {
echo " -".$result2->time."- ";
}
}
}
that produces this for example:
showtimes for 02152013
-1300- -1400- -1500- -1600- -1700-
i use $_GET to get the date and shortname from the URL, then i use the shortname to decide which movie inside the xml that i will be dealing with. i then produce that as a result with the first foreach. i then run a second foreach within the first foreach specifically dealing with the child element that contains the dates and times. i then use an if statement to segregate which date i will be dealing with based on the URL. because of that if statement, i can then echo all of the times within that result where the sibling dates are the same. i would like to echo the times such as: 1300, 1400, 1500, 1600 with no comma following the last time, but i dont know how to do that. i tried using implode(), but because each time echo is inside an if statement it's an object instead of array results. i assume that... i'm not extremely familiar with the terminology. i have instead opted for a space and - before each time and a - and space after each time. it will have to work for now. :)
thanks to all of you guys for your assistance! stackoverflow ROCKS!!!

PHP Array get each Key/Value from XML File

I'm getting stumped by simply trying to get the key/value of a certain tier inside an array I have created from an XML file. The part of the array from Print_R() is:
SimpleXMLElement Object
(
Array
(
[category] => SimpleXMLElement Object
(
[#attributes] => Array
(
[settings] => maximum
)
[cat_1] => 5.21
[cat_2] => 5.05
[cat_3] => 19.36
[cat_4] => 21.97
[cat_5] => 12.17
)
)
)
I am trying to get the "cat_1, cat_2, cat_3 .." keys so that I can put them in their own array and use them for other things. I can do print_r($array) and it works, but when I try and do this:
foreach ($array->category as $key => $val) {
$new_array[$key]= "$val";
}
$array->category doesn't seem to target that list. The "SimpleXMLElement Object" from the XML file seems to be in the way of how I normally use arrays. Does anyone know how I can get to those cat_1 ets. lists?
Notice that $array->category is an object, not an array and cat_* are properties. Since they are all public just use:
$new_array = get_object_vars($array->category);
You should convert simpleXML object to array using
$array = json_decode(json_encode((array) $simplexmlob)), 1);
Then use $array['category'] for other things. There is no need to use foreach loop.

capture the value of an element in array returned by simpleXML in PHP?

Any idea how can i get a single value from an element in array returned by an XML which looks like this?
SimpleXMLElement Object
(
[status] => SimpleXMLElement Object
(
[id] => 0
[description] => Success
)
......
I want to capture the [id] and return that value to run tests against it.
the above was captured using the following
$xml = simplexml_load_string($result);
Thanks
Try this $id = $xml->status->id;
Are you looking for something like:
$sxml = new SimpleXMLElement("<statuses><status><id>0</id><description>success</description></status></statuses>");
var_dump((string) $sxml->status[0]->id);

add to associative array

I have some xml that looks like this:
<?xml version="1.0"?>
<data>
<items>
<item><timestamp>2011-07-11T09:01:42Z</timestamp><title><![CDATA[ some data here ]]></title><link>http://twitter.com/aurl</link></item>
<item><timestamp>2011-05-11T09:01:42Z</timestamp><title><![CDATA[ some data here ]]></title><link>http://twitter.com/aurlhere</link></item>
</items>
and I'm trying to loop over it and add it to an array:
foreach($xml->items->item as $e) {
$feedData['timestamp'] = $e->timestamp;
$feedData['title'] = $e->title;
$feedData['link'] = $e->link;
$feedData['type'] = $e->type;
}
print_r($feedData);
The xml is there and if I put an echo in the foreach I get back 10 responses (whcih are how many items I have) but when I print the array out all I get is one line (which is the last entry in the xml doc).
Array ( [timestamp] => SimpleXMLElement Object ( [0] => 2011-07-08T08:05:19Z ) [title] => SimpleXMLElement Object ( ) [link] => SimpleXMLElement Object ( [0] => http://twitter.com.aurl ) [type] => SimpleXMLElement Object ( ) )
I suspoect I'm overwriting the array on each loop. But why ? It should be adding to the array. Sorry my php isn't great...hence what Is suspect is a bit of a stupid question.
$i = 0;
foreach($xml->items->item as $e) {
$feedData[$i]['timestamp'] = $e->timestamp;
$feedData[$i]['title'] = $e->title;
$feedData[$i]['link'] = $e->link;
$feedData[$i]['type'] = $e->type;
$i++;
}
print_r($feedData);
Well, there is only one $feedData array and you are always setting the value for some specific keys, e.g. $feedData['timestamp']. How do you think this should add to the array? Keys are unique, the same key cannot appear twice, so yes, you are just overwriting the values.
It seems you want an array of arrays:
$feedData = array();
foreach($xml->items->item as $e) {
$feedData[] = array(
'timestamp' => $e->timestamp;
'title' => $e->title;
'link' => $e->link;
'type' => $e->type;
);
}
Have a look at the array manual [docs] for more information about arrays.

Why aren't these values being added to my array as strings?

Further to my question here, I'm actually wondering why I'm not getting strings added to my array with the following code.
I get some HTML from an external source with this:
$doc = new DOMDocument();
#$doc->loadHTML($html);
$xml = #simplexml_import_dom($doc); // just to make xpath more simple
$images = $xml->xpath('//img');
$sources = array();
Here is the images array:
Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[alt] => techcrunch logo
[src] => http://s2.wp.com/wp-content/themes/vip/tctechcrunch/images/logos_small/techcrunch2.png?m=1265111136g
)
)
...
)
Then I added the sources to my array with:
foreach ($images as $i) {
array_push($sources, $i['src']);
}
But when I print the results:
echo "<pre>";
print_r($sources);
die();
I get this:
Array
(
[0] => SimpleXMLElement Object
(
[0] => http://www.domain.com/someimages.jpg
)
...
)
Why isn't $i['src'] treated as a string? Isn't the original [src] element noted where I print $images a string inside there?
To put it another way $images[0] is a SimpleXMLElement, I understand that. But why is the 'src' attribute of THAT object not being but into $sources as a string when I reference it as $i['src']?
Why isn't $i['src'] treated as a string?
Becaue it isn't one - it's a SimpleXMLElement object that gets cast to a string if used in a string context, but it still remains a SimpleXMLElement at heart.
To make it a real string, force cast it:
array_push($sources, (string) $i['src']);
Because SimpleXMLElement::xpath() (quoting) :
Returns an array of SimpleXMLElement
objects
and not an array of strings.
So, the items of your $images array are SimpleXMLElement objects, and not strings -- which is why you have to cast them to strings, if you want strings.

Categories