SimpleXML Xpath result array split into pages - php

Is there a easy way to separate the output from SimpleXML into pages? Let's say the XML file got 200 elements but I want to split it into 20 elements on each page. So it would be like index.php?page=1?
$xml = new SimpleXMLElement(file_get_contents("demofile.xml"));
$per_no = $xml->children();
echo count($per_no) . ' are now active<br />';
$cnt = 0;
foreach ($xml->xpath('/webcams_online/webcam') as $node) {
if ($cnt == 10) {
break;
}
$itemXML = array(
'account' => $node['account'],
'nickname' => $node['nickname'],
'number_visitors' => $node['number_visitors']
);
$cnt++;
?>
<?php echo $itemXML['account']; ?>
<?php
}

Related

Php html parsing, I want to save parsed elements into an array

I'm trying to parse the html page and accessing some of the tags. I am parsing all of those tags and displaying the result in form of indentation which is according to the level of tags e.g. header tags h1, h2, h3 etc. Now, I want to save the resultant data (indented table of contents) into an array along with the name of the tags. Kindly help me to sort out my problem.
Here is my php code... I'm using html dom parser.
include ("simple_html_dom.php");
session_start();
error_reporting(0);
$string = file_get_contents('test.php');
$tags = array(0 => '<h1', 1 => '<h2', 2 => '<h3', 3 => '<h4', 4 => '<h5', 5 => '<h6');
function parser($html, $needles = array()){
$positions = array();
foreach ($needles as $needle){
$lastPos = 0;
while (($lastPos = strpos($html, $needle, $lastPos))!== false)
{
$positions[] = $lastPos;
$lastPos = $lastPos + strlen($needle);
}
unset($needles[0]);
if(count($positions) > 0){
break;
}
}
if(count($positions) > 0){
for ($i = 0; $i < count($positions); $i++) {
?>
<div class="<?php echo $i; ?>" style="padding-left: 20px; font-size: 14px;">
<?php
if($i < count($positions)-1){
$temp = explode('</', substr($html, $positions[$i]+4));
$pos = strpos($temp[0], '>');
echo substr($temp[0], $pos);
parser(substr($html, $positions[$i]+4, $positions[$i+1]-$positions[$i]-4), $needles);
} else {
$temp = explode('</', substr($html, $positions[$i]+4));
$pos = strpos($temp[0], '>');
echo substr($temp[0], $pos+1);
parser(substr($html, $positions[$i]+4), $needles);
}
?>
</div>
<?php
}
} else {
// not found any position of a tag
}
}
parser($string, $tags);
If you wanted to do it using SimpleXML and XPath, there is a shorter and much more readable version you could try...
$xml = new SimpleXMLElement($string);
$tags = $xml->xpath("//h1 | //h2 | //h3 | //h4");
$data = [];
foreach ( $tags as $tag ) {
$elementData['name'] = $tag->getName();
$elementData['content'] = (string)$tag;
$data[] = $elementData;
}
print_r($data);
You can see the pattern in the XPath - it combines any of the elements you need. The use of // means to find at any level and then the name of the element you want to find. These are combined using |, which is the 'or' operator. This could easily be expanded using the same type of expression to build a full set of tags you need.
The program then loops over the elements found and builds an array of each element at a time. Taking the name and content and adding them to the $data array.
Update:
If your file isn't well formed XML, you may have to use DOMDocument and loadHTML. Only a slight difference but is more tollerant of errors...
$string = file_get_contents("links.html");
$xml = new DOMDocument();
libxml_use_internal_errors();
$xml->loadHTML($string);
$xp = new DOMXPath($xml);
$tags = $xp->query("//h1 | //h2 | //h3 | //h4");
$data = [];
foreach ( $tags as $tag ) {
$elementData['name'] = $tag->tagName;
$elementData['content'] = $tag->nodeValue;
$data[] = $elementData;
}
print_r($data);

Printing out an array to a file

I'm stuck on particular task. As you can see I'm extracting hrefs and title from webpage and I need to put this information to a file. But how this array can be printed in order like this: href1 : title1 , href2 : title2 and so on.
<?php
$searched = file_get_contents('http://technologijos.lt');
$xml = new DOMDocument();
#$xml->loadHTML($searched);
foreach($xml->getElementsByTagName('a') as $lnk)
{
$links[] = array(
'href' => $lnk->getAttribute('href'),
'title' => $lnk->getAttribute('title')
);
}
echo '<pre>'; print_r($links); echo '</pre>';
?>
Why not create the array directly in a way that is usable afterwards?
<?php
$searched = file_get_contents('http://technologijos.lt');
$xml = new DOMDocument();
#$xml->loadHTML($searched);
$links = [];
foreach($xml->getElementsByTagName('a') as $lnk) {
$links[] = sprintf(
'%s : %s',
$lnk->getAttribute('href'),
$lnk->getAttribute('title');
);
}
var_dump(implode(', ', $links);
Obviously the same can be done by using a second loop to iterate over the links array if it is create as shown in your example.

viewing XML data if attribute value equals variable value

I'm stuck on something extremely simple.
Here is my xml feed:
http://xml.betfred.com/Horse-Racing-Daily.xml
Here is my code
<?php
function HRList5($viewbets) {
$xmlData = 'http://xml.betfred.com/Horse-Racing-Daily.xml';
$xml = simplexml_load_file($xmlData);
$curdate = date('d/m/Y');
$new_array = array();
foreach ($xml->event as $event) {
if($event->bettype->attributes()->bettypeid == $viewbets){//$_GET['evid']){
// $eventid = $_GET['eventid'];
// if ($limit == $c) {
// break;
// }
// $c++;
$eventd = substr($event->attributes()->{'date'},6,2);
$eventm = substr($event->attributes()->{'date'},4,2);
$eventy = substr($event->attributes()->{'date'},0,4);
$eventt = $event->attributes()->{'time'};
$eventid = $event->attributes()->{'eventid'};
$betname = $event->bettype->bet->attributes()->{'name'};
$bettypeid = $event->bettype->attributes()->{'bettypeid'};
$betprice = $event->bettype->bet->attributes()->{'price'};
$betid = $event->bettype->bet->attributes()->{'id'};
$new_array[$betname.$betid] = array(
'betname' => $betname,
'viewbets' => $viewbets,
'betid' => $betid,
'betname' => $betname,
'betprice' => $betprice,
'betpriceid' => $event->bettype->attributes()->{'betid'},
);
}
ksort($new_array);
$limit = 10;
$c = 0;
foreach ($new_array as $event_time => $event_data) {
// $racedate = $event_data['eventy'].$event_data['eventm'].$event_data['eventd'];
$today = date('Ymd');
//if($today == $racedate){
// if ($limit == $c) {
// break;
//}
//$c++;
$replace = array("/"," ");
// $eventname = str_replace($replace,'-', $event_data['eventname']);
//$venue = str_replace($replace,'-', $event_data['venue']);
echo "<div class=\"units-row unit-100\">
<div class=\"unit-20\" style=\"margin-left:0px;\">
".$event_data['betprice']."
</div>
<div class=\"unit-50\">
".$event_data['betname'].' - '.$event_data['betprice']."
</div>
<div class=\"unit-20\">
<img src=\"betnow.gif\" ><br />
</div>
</div>";
}
}//echo "<strong>View ALL Horse Races</strong> <strong>>></strong>";
//var_dump($event_data);
}
?>
Now basically the XML file contains a list of horse races that are happening today.
The page I call the function on also declares
<?php $viewbets = $_GET['EVID'];?>
Then where the function is called I have
<?php HRList5($viewbets);?>
I've just had a play around and now it displays the data in the first <bet> node
but the issue is it's not displaying them ALL, its just repeating the 1st one down the page.
I basically need the xml feed queried & if the event->bettype->attributes()->{'bettypeid'} == $viewbets I want the bet nodes repeated down the page.
I don't use simplexml so can offer no guidance with that - I would say however that to find the elements and attributes you need within the xml feed that you ought to use an XPath query. The following code will hopefully be of use in that respect, it probably has an easy translation into simplexml methods.
Edit: Rather than targeting each bet as the original xpath did which then caused issues, the following should be more useful. It targets the bettype and then processes the childnodes.
/* The `eid` to search for in the DOM document */
$eid=25573360.20;
/* create the DOM object & load the xml */
$dom=new DOMDocument;
$dom->load( 'http://xml.betfred.com/Horse-Racing-Daily.xml' );
/* Create a new XPath object */
$xp=new DOMXPath( $dom );
/* Search the DOM for nodes with particular attribute - bettypeid - use number function from XSLT to test */
$oCol=$xp->query('//event/bettype[ number( #bettypeid )="'.$eid.'" ]');
/* If the query was successful there should be a nodelist object to work with */
if( $oCol ){
foreach( $oCol as $node ) {
echo '
<h1>'.$node->parentNode->getAttribute('name').'</h1>
<h2>'.date('D, j F, Y',strtotime($node->getAttribute('bet-start-date'))).'</h2>';
foreach( $node->childNodes as $bet ){
echo "<div>Name: {$bet->getAttribute('name')} ID: {$bet->getAttribute('id')} Price: {$bet->getAttribute('price')}</div>";
}
}
} else {
echo 'XPath query failed';
}
$dom = $xp = $col = null;

How parse RSS feed

I'm trying to parse an RSS feed in PHP for the first time. It seems to go fine until I actually try to display anything! This example is me trying to pull out four random organization names from the feed (I actually want to display more, but am keeping it simple here...)
$xml = file_get_contents('https://rss.myinterfase.com/rss/oxford_RSS_Jobs_xml.xml');
foreach($xml->Row as $job) {
$item[] = array(
'OrganizationName' => (string)$job->OrganizationName,
'job_JobTitle' => (string)$job->job_JobTitle,
'job_expiredate' => strtotime($job->job_expiredate),
'ExternalLink' => $job->ExternalLink
);
}
$rand_job = array_rand($item, 4);
$i=0;
echo '<ul>';
while($i<=3) {
echo '<li>';
echo $item[$i]['OrganizationName'];
echo '</li>';
$i++;
}
echo '</ul>'
What do I need to do differently? Thanks!
You have to use simplexml_load_file($url); or similar.
$url = 'https://rss.myinterfase.com/rss/oxford_RSS_Jobs_xml.xml';
$xml = simplexml_load_file($url);
foreach($xml->row as $job) { // be sure about $xml->row. If it's full path to this elements
//..... your code
}

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