Got stuck parsing tabular content from a website - php

I've written a script in PHP to get the tabular data from a webpage. When I execute my script I can get them in a single column. However, I wish to parse them as a list, as in how they look like in that webpage.
Website link
To be clearer:
My current output are like:
978
EMU
EUR
1
118.2078
36
Australija
AUD
1
73.1439
My expected output are like:
['978', 'EMU', 'EUR', '1', '118.2078']
['36', 'Australija', 'AUD', '1', '73.1439']
['124', 'Kanada', 'CAD', '1', '77.7325']
['156', 'Kina', 'CNY', '1', '14.6565']
['191', 'Hrvatska', 'HRK', '1', '15.9097']
This is my try so far:
<?php
$url = "http://www.nbs.rs/kursnaListaModul/srednjiKurs.faces?lang=lat";
$dom = new DomDocument;
$dom->loadHtmlFile($url);
$xpath = new DomXPath($dom);
$rowData = array();
foreach ($xpath->query('//tbody[#id="index:srednjiKursList:tbody_element"]//tr') as $node) {
foreach ($xpath->query('td', $node) as $cell) {
$rowData[] = $cell->nodeValue;
}
}
foreach($rowData as $rows){
echo $rows . "<br/>";
}
?>

You are adding each element one at a time to the output array, you probably wanted to build up a row at a time and output that...
$rowData = array();
foreach ($xpath->query('//tbody[#id="index:srednjiKursList:tbody_element"]//tr') as $node) {
$row = array();
foreach ($xpath->query('td', $node) as $cell) {
$row[] = $cell->nodeValue;
}
$rowData[] = $row;
}
foreach($rowData as $rows){
print_r($rows); // Format the data as needed
}

Try this.
$htmlContent = file_get_contents("http://www.nbs.rs/kursnaListaModul/srednjiKurs.faces?lang=lat");
$DOM = new DOMDocument();
$DOM->loadHTML($htmlContent);
$Header = $DOM->getElementsByTagName('th');
$Detail = $DOM->getElementsByTagName('td');
//#Get header name of the table
foreach($Header as $NodeHeader)
{
$aDataTableHeaderHTML[] = trim($NodeHeader->textContent);
}
//#Get row data/detail table without header name as key
$i = 0;
$j = 0;
foreach($Detail as $sNodeDetail)
{
$aDataTableDetailHTML[$j][] = trim($sNodeDetail->textContent);
$i = $i + 1;
$j = $i % count($aDataTableHeaderHTML) == 0 ? $j + 1 : $j;
}
//print_r($aDataTableDetailHTML)
//#Get row data/detail table with header name as key and outer array index as row number
for($i = 0; $i < count($aDataTableDetailHTML); $i++)
{
for($j = 0; $j < count($aDataTableHeaderHTML); $j++)
{
#$aTempData[$i][$aDataTableHeaderHTML[$j]] = $aDataTableDetailHTML[$i][$j];
}
}
$aDataTableDetailHTML = $aTempData; unset($aTempData);
print_r($aDataTableDetailHTML);

Related

Index in for loop not returning last index

I have an image gallery and each is saved by index.. gallery1: /image here.. gallery2: / image here.. etc..
I'm using an index with multiple for loops to return the images and by column because it's either Masonry or rectangular. I am getting the return fine except for the very last index.
private function rectangle($items, $columns, $contents = array()) {
$thumbs = array('talent_thumbnail','360x207');
$arr = array();
$col = round(count($items) / $columns);
$perCol = floor(count($items) / $columns);
$extra = count($items) % $columns;
$ind = 1;
$length = count($items);
$arr = array();
for($i = 0; $i < $columns && $ind < $length; $i++) {
$temp = array();
for($j = 0; $j < $perCol; $j++) {
$obj = new JObject();
$obj->image = $items['gallery' . $ind]['photo'];
$obj->alt_text = $items['gallery'. $ind]['alt_text'];
$temp[] = $obj;
$ind++;
}
if ($extra > 0) {
$obj = new JObject();
$obj->image = $items['gallery'. $ind]['photo'];
$obj->alt_text = $items['gallery'. $ind]['alt_text'];
$temp[] = $obj;
$ind++;
$extra--;
}
$arr[] = $temp;
}
}
I know it can't be that hard but I'm not that good at it right yet.
Any help is so much welcome.
Thank You.
You set the variable $ind to 1, count the length of the array, and then initialize the for loop with the condition $ind < $length.
When $ind reaches the index needed to access the last item, the loop is not run again, since $ind is now equal to $length, not smaller.
You can fix this by changing the condition in your for-loop to "less or equal":
$i < $columns && $ind <= $length
This runs the loop once more when $ind has reached the last index.
Probably the problem is at this line:
$ind = 1;
In PHP non-associative arrays have the indexes starting to 0 instead of 1:
$arr = array('a', 'b', 'c');
print_r($arr);
// output:
Array ( [0] => a [1] => b [2] => c )
So, try to change that line in your code to:
$ind = 0;
Complete code:
private function rectangle($items, $columns, $contents = array()) {
$thumbs = array('talent_thumbnail','360x207');
$arr = array();
$col = round(count($items) / $columns);
$perCol = floor(count($items) / $columns);
$extra = count($items) % $columns;
$ind = 0;
$length = count($items);
$arr = array();
for($i = 0; $i < $columns && $ind < $length; $i++) {
$temp = array();
for($j = 0; $j < $perCol; $j++) {
$obj = new JObject();
$obj->image = $items['gallery' . $ind]['photo'];
$obj->alt_text = $items['gallery'. $ind]['alt_text'];
$temp[] = $obj;
$ind++;
}
if ($extra > 0) {
$obj = new JObject();
$obj->image = $items['gallery'. $ind]['photo'];
$obj->alt_text = $items['gallery'. $ind]['alt_text'];
$temp[] = $obj;
$ind++;
$extra--;
}
$arr[] = $temp;
}
}

adding new key value is not working

This is my json link which stored in variable named $onceBooking.
I want to count total booking days. If booking array is empty then add total_days = 0 but but if it is not empty then i am counting the unique booking_slots and adding them into main array. I am getting the correct count but when i am adding this into main it showing me this error.
$data = json_decode($onceBooking);
for ($i = 0; $i < count($data); $i++) {
if (count($data[$i]->bookings) == 0) {
$data[$i]->total_days = 0;
} else {
$bookings = $data[$i]->bookings;
for ($j = 0; $j < count($bookings); $j++) {
$booking_slots = $bookings[$j]->booking_slots;
$final_array = array();
$uniquekeys = array();
foreach ($booking_slots as $key => $data) {
if (!in_array($data->date, $uniquekeys)) {
$uniquekeys[] = $data->date;
$final_array[$key] = $data;
}
}
}
$data[$i]->total_days = count($final_array);
}
}
return $data;
Change your call to json_decode() to return an array by adding true as the 2nd argument.
// change this
$data = json_decode($onceBooking);
// to this
$data = json_decode($onceBooking, true);

How to increase columns in PHP excel

I am making dynamic columns and my columns are 1000+ , can anybody guide me how to increase columns in PHPexcel. How can I increase my column length while creating dynamic columns? or Is there any other way For your reference I am showing my code below:
private function _buildExcellTableData(ExportExcel $excel)
{
$excel->row++;
$excel->row++;
$sheet = $excel->excel->getActiveSheet();
$sheet->setCellValue('D1', 'Role Requirement Report');
$header1 = $sheet->mergeCells('D1:G1')->getStyle('D1');
$header1->getFont()->setSize(18)->setBold(true);
$header1->getFill()->setFillType(\PHPExcel_Style_Fill::FILL_SOLID)->getStartColor()->setRGB('E6E6E6');
$alpha = 'B';
$countCells = count($this->data['roles']);
$header = $sheet->getStyle('A'.$excel->row);
$header->getFont()->setBold(true);
$header->getFill()->setFillType(\PHPExcel_Style_Fill::FILL_SOLID)->getStartColor()->setRGB('E6E6E6');
$sheet->getStyle('A'.$excel->row)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_RIGHT);
$sheet->getColumnDimension('A')->setAutoSize(TRUE);
$sheet->setCellValue('A'.$excel->row, 'Roles/Requirements');
$rolesIds = array_map(create_function('$o', 'return $o->id;'), $this->data['roles']);
foreach($this->data['roles'] as $key=>$value)
{
for ($i = 0; $i < $countCells; $i++)
{
$sheet->getColumnDimension($alpha)->setAutoSize(TRUE);
$sheet->setCellValue($alpha.'6',$value->title);
}
$alpha++;
}
$row_start = $excel->row;
foreach ($this->data['rolesrequirement'] as $key=>$row)
{
$excel->row++;
$sheet->setCellValue('A' . $excel->row, $row->title);
$roleCheck = array_map('trim', explode(',', $row->roleid));
$alpha = 'B';
for ($i = 0; $i < $countCells; $i++)
{
$value = (in_array($rolesIds[$i], $roleCheck)) ? 'x' : '';
$sheet->getStyle($alpha.$excel->row)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
$sheet->setCellValue($alpha.$excel->row, $value);
$alpha++;
}
}
$row_style = $sheet->getStyle('A'.$row_start);
$row_style->getBorders()->getAllBorders()->setBorderStyle(\PHPExcel_Style_Border::BORDER_THIN);
}
Thanks in advance!

how to read only part of an xml file with php xmlreader

I have an RSS xml file that is pretty large, with more than 700 nodes.
I am using XMLReader Iterator library to parse it and display the results as 10 per page.
This is my sample code for parsing xml:
<?php
require('xmlreader-iterators.php');
$xmlFile = 'http://www.example.com/rss.xml';
$reader = new XMLReader();
$reader->open($xmlFile);
$itemIterator = new XMLElementIterator($reader, 'item');
$items = array();
foreach ($itemIterator as $item) {
$xml = $item->asSimpleXML();
$items[] = array(
'title' => (string)$xml->title,
'link' => (string)$xml->link
);
}
// Logic for displaying the array values, based on the current page.
// page = 1 means $items[0] to $items[9]
for($i = 0; $i <= 9; $i++)
{
echo ''.$items[$i]['title'].'<br>';
}
?>
But the problem is that, for every page, i am parsing the entire xml file and then just displaying the corresponding page results, like: if the page is 1, displaying the 1 to 10 nodes, and if the page is 5, displaying 41 to 50 nodes.
It is causing delay in displaying data. Is it possible to read just the nodes corresponding to the requested page? So for the first page, i can read nodes from 1 to 10 positions, instead of parsing all the xml file and then display first 10 nodes. In other words, can i apply a limit while parsing an xml file?
I came across this answer of Gordon that addresses a similar question, but it is using SimpleXML, which is not recommended for parsing large xml files.
use array_splice to extract the portion of array
require ('xmlreader-iterators.php');
$xmlFile = 'http://www.example.com/rss.xml';
$reader = new XMLReader();
$reader->open($xmlFile);
$itemIterator = new XMLElementIterator($reader, 'item');
$items = array();
$curr_page = (0 === (int) $_GET['page']) ? 1 : $_GET['page'];
$pages = 0;
$max = 10;
foreach ($itemIterator as $item) {
$xml = $item->asSimpleXML();
$items[] = array(
'title' => (string) $xml->title,
'link' => (string) $xml->link
);
}
// Take the length of the array
$len = count($items);
// Get the number of pages
$pages = ceil($len / $max);
// Calculate the starting point
$start = ceil(($curr_page - 1) * $max);
// return the portion of results
$arrayItem = array_slice($items, $start, $max);
for ($i = 0; $i <= 9; $i ++) {
echo '' . $arrayItem[$i]['title'] . '<br>';
}
// pagining stuff
for ($i = 1; $i <= $pages; $i ++) {
if ($i === (int) $page) {
// current page
$str[] = sprintf('<span style="color:red">%d</span>', $i);
} else {
$str[] = sprintf('%d', $i, $i);
}
}
echo implode('', $str);
Use cache in this case, since you cannot parse partially an XML.
Check this
<?php
if($_GET['page']!=""){
$startPagenew = $_GET['page'];
$startPage = $startPagenew-1;
}
else{
$startPage = 0;
}
$perPage = 10;
$currentRecord = 0;
$xml = new SimpleXMLElement('http://sports.yahoo.com/mlb/teams/bos/rss.xml', 0, true);
echo $startPage * $perPage;
foreach($xml->channel->item as $key => $value)
{
$currentRecord += 1;
if($currentRecord > ($startPage * $perPage) && $currentRecord < ($startPage * $perPage + $perPage)){
echo "$value->title";
echo "<br>";
}
}
//and the pagination:
//echo $currentRecord;
for ($i = 1; $i <= ($currentRecord / $perPage); $i++) {
echo("<a href='xmlpagination.php?page=".$i."'>".$i."</a>");
} ?>
Updated
Check this Link
http://www.phpclasses.org/package/5667-PHP-Parse-XML-documents-and-return-arrays-of-elements.html
You can use Dom and Xpath. It should be much faster, since Xpath allows you to select nodes by their position in a list.
<?php
$string = file_get_contents("http://oar.icrisat.org/cgi/exportview/subjects/s1=2E2/RSS2/s1=2E2.xml");
$dom = new DOMDocument('1.0', 'utf-8');
$dom->loadXML($string);
$string = "";
$xpath = new DOMXPath($dom);
$channel = $dom->getElementsByTagName('channel')->item(0);
$numItems = $xpath->evaluate("count(item)", $channel);
// get your paging logic
$start = 10;
$end = 20;
$items = $xpath->evaluate("item[position() >= $start and not(position() > $end)]", $channel);
$count = $start;
foreach($items as $item) {
print_r("\r\n_____Node number $count ");
print_r( $item->nodeName);
$childNodes = $item->childNodes;
foreach($childNodes as $childNode) {
print_r($childNode->nodeValue);
}
$count ++;
}

Print Terms in Node in Multiple Columns Sorted in Downward Order

I have approximately 20 content-taxonomy check boxes from one field ("features"). The checked terms display in node-example.tpl.php. I am trying to show these content-taxonomy terms in two columns displayed/sorted in a downward order instead of across.
I am trying to cobble two bits of code to accomplish this...but my php skills are not yet up to the challenge. I can't get all of the array values generated in the foreach loop to be recognized by the second section of code.
The code below was taken (and modified) from the following sources:
http://drupal.org/node/312812
roscripts.com/PHP_display_data_on_columns-127.html
I am trying to use the following code in my node-example.tpl.php file.
<?php
echo '<table>';
foreach ($node->field_features as $delta => $value){
$term = taxonomy_get_term($node->field_features[$delta]['value']);
$term_name = check_plain($term->name);
}
// Default # of Columns
$numcols = 2;
// Number of Items
$numitems = count($term_name);
// Number of Rows
$numrows = ceil($numitems/$numcols);
for ($row=1; $row <= $numrows; $row++)
{
$cell = 0;
echo ' <tr>'."\n";
for ($col=1; $col <= $numcols; $col++)
{
echo ' <td>'."\n";
if ($col===1)
{
$cell += $row;
print $term_name[$cell - 1];
}
else {
$cell += $numrows;
print $term_name[$cell - 1];
}
echo ' </td>'."\n";
}
echo ' </tr>'."\n";
}
echo '</table>';
?>
Ok, I got this to work using the answer to another foreach-loop question/answer on this site.
Declare the $items array outside the
loop and use $items[] to add items to
the array.
This is the final code that does exactly what I wanted.
<?php
echo '<table>';
$items = array();
foreach ($node->field_features as $delta => $value)
{
$term = taxonomy_get_term($node->field_features[$delta]['value']);
$term_name = check_plain($term->name);
$items[] = $term_name;
}
// Default # of Columns
$numcols = 2;
// Number of Items
$numitems = count($items);//print $numitems;
// Number of Rows
$numrows = ceil($numitems/$numcols);//print $numrows;
for ($row=1; $row <= $numrows; $row++)
{
$cell = 0;
echo ' <tr>'."\n";
for ($col=1; $col <= $numcols; $col++)
{
echo ' <td>'."\n";
if ($col===1)
{
$cell += $row;
print $items[$cell - 1];
}
else {
$cell += $numrows;
print $items[$cell - 1];
}
echo ' </td>'."\n";
}
echo ' </tr>'."\n";
}
echo '</table>';
?>
You can use theme('table', $headers, $rows) to render your table using the theme engine.
// Default # of Columns
$numcols = 2;
$rows = array();
$cell_count = 0;
foreach ($node->field_features as $delta => $value) {
$term = taxonomy_get_term($node->field_features[$delta]['value']);
$term_name = check_plain($term->name);
$cell_count += 1;
$row_index = floor($cell_count / $numcols);
$rows[$row_index][] = $term_name;
}
print theme('table', array(), $rows);

Categories