Errors simplexml - Complicated URL - php

I am trying to display items from an XML feed on a page
This is my code...
$feed = 'http://awebsite.co.uk/directory/rssfeed.php?thecondition=(title%20LIKE%20'%british%'%20OR%20description%20LIKE%20'%british%')';
$xml = simplexml_load_file("$feed");
if ( $xml->channel->item !='' ) {
foreach ($xml->channel->item as $item) {
echo '<li>' . $item->title . '</li>';
}
}
else { echo 'None'; }
However, due to the complicated feed URL it is giving lots of errors.
Note: I have changed the domain in the URL for this example.
How can I make this work?

Can't judge anything without seeing the XML source first but if it's a standard RSS channel file you should be iterating through your items something like this:
$items = $xml->xpath('/channel/item');
foreach ($items as $item) {
echo '<li>' . $item->title . '</li>';
}
Also the initial condition: if ( $xml->channel->item !='' ) {/*...*/} isn't really going to work.

Related

Grouping/Ordering Items in PHP Object Array

I have a sitemap that I'm trying to group by URL and stack them based on URL. Here is the sitemap https://www.sitecentre.com.au/sitemap
Basically, I need this to be dynamic. I can make this easily by doing a case, or if statements, like I've done on the Blog section, but I need it dynamic. It needs to look like this:
<li>Web Design
<ul>
<li>Nested in Web Design</li>
<li>Nested in Web Design</li>
</ul>
</li>
All based on the URL. the URL is /design then the nested would be design/nested
Then the next group would be like branding and nested on branding so it's all organised and laid out perfectly, then alphabetically ordered based on something else.
Here is our current PHP:
<?php
$pages = json_decode(file_get_contents('data/pages.json'));
foreach ($pages as $data){
foreach ($data as $key => $values){
if ($values->status === '1' && $values->visible === '1' && $values->slug !== 'home'){
if ($values->slug !== 'blog'){
echo '<li>' . $values->heading . ' - Last Updated: ' . date('d/m/Y', strtotime($values->date_modified)) . '</li>';
} else {
// Get the latest blogs
$blogs = json_decode(file_get_contents('data/blogs.json'));
echo '<li>' . $values->heading . ' - Last Updated: ' . date('d/m/Y', strtotime($values->date_modified)) . '';
echo '<ul>';
foreach ($blogs as $data){
foreach ($data as $key => $values){
if ($values->status === '1' && $values->visible === '1'){
echo '<li>' . $values->heading . ' - Last Updated: ' . date('d/m/Y', strtotime($values->date_modified)) . '</li>';
}
}
}
echo '</li></ul>';
}
}
}
}
?>
It clearly needs a bit of work in order to make this work, but I cannot for the life of me work out where to start.

Traverse XML file to find products recursively

I am trying to read remote XML file to find products in a specific category. I am facing issue because XML file has nested categories and each category has products. I need help in preparing a recursive function which will output products from a specific category given the category name.
Here is the code i have started with
<?php
$xml = simplexml_load_file('https://www.deere.com/en/us-en.taxonomy');
getProducts($xml);
function getProducts($xml) {
foreach ($xml as $obj) {
if ($obj->getName() == 'en_us_tractors') { //if category name is en_us_tractors
if ($obj->children()) {
foreach ($obj->children() as $child) {
echo '<h1>' . $child->name . '</h1>';
if ($child->products) {
foreach ($child->products as $product) {
foreach ($product as $p) {
echo 'sku is ' . $p->sku . '<br>';
echo 'path is ' . $p->path . '<br>';
}
}
}
}
}
}
}
}
It's simple to use XPath to find the data, this finds all of the products inside the category you want...
$xml = simplexml_load_file('https://www.deere.com/en/us-en.taxonomy');
$products = $xml->xpath("//en_us_tractors//products/*");
foreach ( $products as $product ){
echo $product->sku."/".$product->path.PHP_EOL;
}

JSON: Ignoring same-name records inside nested objects, and retrieving the-pair-name records outside

I'm accessing a search API that gives json result like: Free Search API
I want to retrieve only the records title, kwic, and url in the object results into my code. But the title and url in the object related are standing in the way.
I have tried doing some if function:
foreach ($json->results as $item) {
if (isset($item->kwic)) {
$rss_item = array(
'title' => $item->title,
'kwic' => $item->kwic,
'url' => $item->url,
);
array_push($desArray, $item->kwic);
}
else {
return false;
}
array_push($rss_array, $rss_item);
for ($i = 0; $i < 50; $i++) {
echo '' . $rss_array[$i]['title'] . '' . '<img src="http://corrupteddevelopment.com/wp-content/uploads/2012/10/open-new-tab-window-icon.jpg" width="15px" height="15px"><br/>';//LINE 66
echo '<hr/>';
echo '<p>' . $rss_array [$i]['kwic'] . '</p></br>';
}
It gave me partly results, and partly : Notice: Undefined offset: 31 in C:\xampp\htdocs\MSP\SignIn\cariFree.php on line 66. When I wrote:
if (isset($item->related)) {
return false}
It gave me entirely blank page.
What have I missed?
Thank you.
Here is the screen-shoot of the full code: mycode.php
I rewrote your code a bit, I think that this is what you actually should be doing, but I'm not sure since I dont have the entire code and don't really understand what your problem is (apart from bad coding).
<?php
//first off use arrays instead of objects:
$json = json_decode($data, true);
foreach ( $json['results'] as $item ) {
if ( isset($item['kwic']) ) {
//we can push $item into the rss_array directly
array_push($rss_array, $item); #I assume you want this here instead of outside the loop
}
//I removed the else since it seemed completly stupid
}
foreach ( $rss_array as $item ) {
echo '' . $item['title'] . '' . '<img src="http://corrupteddevelopment.com/wp-content/uploads/2012/10/open-new-tab-window-icon.jpg" width="15px" height="15px"><br/>';//LINE 66
echo '<hr/>';
echo '<p>' . $item['kwic'] . '</p></br>';
}

PHP how to count xml elements in object returned by simplexml_load_file(),

I have inherited some PHP code (but I've little PHP experience) and can't find how to count some elements in the object returned by simplexml_load_file()
The code is something like this
$xml = simplexml_load_file($feed);
for ($x=0; $x<6; $x++) {
$title = $xml->channel[0]->item[$x]->title[0];
echo "<li>" . $title . "</li>\n";
}
It assumes there will be at least 6 <item> elements but sometimes there are fewer so I get warning messages in the output on my development system (though not on live).
How do I extract a count of <item> elements in $xml->channel[0]?
Here are several options, from my most to least favourite (of the ones provided).
One option is to make use of the SimpleXMLIterator in conjunction with LimitIterator.
$xml = simplexml_load_file($feed, 'SimpleXMLIterator');
$items = new LimitIterator($xml->channel->item, 0, 6);
foreach ($items as $item) {
echo "<li>{$item->title}</li>\n";
}
If that looks too scary, or not scary enough, then another is to throw XPath into the mix.
$xml = simplexml_load_file($feed);
$items = $xml->xpath('/rss/channel/item[position() <= 6]');
foreach ($items as $item) {
echo "<li>{$item->title}</li>\n";
}
Finally, with little change to your existing code, there is also.
$xml = simplexml_load_file($feed);
for ($x=0; $x<6; $x++) {
// Break out of loop if no more items
if (!isset($xml->channel[0]->item[$x])) {
break;
}
$title = $xml->channel[0]->item[$x]->title[0];
echo "<li>" . $title . "</li>\n";
}
The easiest way is to use SimpleXMLElement::count() as:
$xml = simplexml_load_file($feed);
$num = $xml->channel[0]->count();
for ($x=0; $x<$num; $x++) {
$title = $xml->channel[0]->item[$x]->title[0];
echo "<li>" . $title . "</li>\n";
}
Also note that the return of $xml->channel[0] is a SimpleXMLElement object. This class implements the Traversable interface so we can use it directly in a foreach loop:
$xml = simplexml_load_file($feed);
foreach($xml->channel[0] as $item {
$title = $item->title[0];
echo "<li>" . $title . "</li>\n";
}
You get count by count($xml).
I always do it like this:
$xml = simplexml_load_file($feed);
foreach($xml as $key => $one_row) {
echo $one_row->some_xml_chield;
}

Parsing Last.fm feed onto website using PHP

I'm trying to parse the Last.fm feed of my last 10 tracks played onto my website.
This is what I have so far,
<?php
$doc = new DOMDocument();
$doc->load('http://ws.audioscrobbler.com/1.0/user/nathanjmassey/recenttracks.xml');
$arrFeeds = array();
foreach ($doc->getElementsByTagName('track') as $node) {
$itemRSS = array (
'artist' => $node->getElementsByTagName('artist')->item(0)->nodeValue,
'name' => $node->getElementsByTagName('name')->item(0)->nodeValue,
'url' => $node->getElementsByTagName('url')->item(0)->nodeValue,
);
array_push($arrFeeds, $itemRSS);
}
?>
<?php
foreach ($arrFeeds as $i => $values) {
foreach ($values as $key => $value) {
print "<p>$value\n</p>";
}
}
?>
This basically gives me all 10 tracks in the feed in the format,
Linkin Park
In Between
http://www.last.fm/music/Linkin+Park/_/In+Between
But I need to format the results in list of links such as,
$artist - $track
How would I extend my script to achieve this?
For your output, use this:
<?
foreach ($arrFeeds as $i => $values)
{
print "<a href='" . $values['url'] . "'>" . $values['artist'] . " - " . $values['name'] . "</a>";
}
?>
UPDATE: How to limit # of parsed items
(Responding to the comment via edit so I can use the code display tags.)
I'm at work at the moment, but I'd try changing your initial parsing code something like so:
array_push($arrFeeds, $itemRSS); // existing line
if (count($arrFeeds) >= 5) { break; } // add this line

Categories