You are here:  » How can I count the number of items in an xml file?

Support Forum



How can I count the number of items in an xml file?

Submitted by travelfrog on Wed, 2006-05-03 13:09 in

I am working on a pagination script to split up the results of an imported xml file. I want to display 10 items per page, but in order to create the individual page numbers, I need to know the total number of items that are listed in the xml file. How would I go about this?

I have used $x = count($item); inside the myRecordHandler($item) function, but when I echo $x, it just displays the total that is paged so far (page1 displays 10 items, page2 displays 20 items)and not the total amount of items.

Anyone help please?

Submitted by support on Wed, 2006-05-03 13:18

Hiya,

Because the parsing is a serial process (one record after another); there is unfortunately no way of getting a record count "up front" without actually parsing the entire file.

If you are working with small feeds then it may not be too much of an overhead; but with large files it may take several seconds just to get the record count, and you would have to do this on every page.

The basic code to count records would be as follows:

<?php
  
require("MagicParser.php");
  
// initialise counter
  
$recordCount 0;
  function 
myRecordCounter($record)
  {
    global 
$recordCount;
    
// increment for each record in the feed
    
$recordCount++;
  }
  
// parse the file to count records
  
MagicParser_parse("file.xml","myRecordCounter");
  
// display the total
  
print "Total Record: ".$recordCount;
?>

My recommendation would be to design your pagniation without a requirement for knowing the total number of records (for example, displaying a "Next" link only rather than links to each page) as this will have far less of a performance overhead.

Hope this helps!
David.

Submitted by travelfrog on Thu, 2006-05-04 14:27

Hi David,

Thank you for the prompt help. Using the information that you have provided, I have managed to count all of the items and paginate the results.

I do still have one problem in that the pagination is displaying 10 items on the first page, and then 11 items on all other pages. How can I correct the number of items displayed?

Here is the script that I currently have - you may notice that I have changed some of the descriptions of the variables.

<?php
require $_SERVER['DOCUMENT_ROOT'].'/magic-parser/MagicParser.php';
if(!
$_GET['page'])$page 1;// If there is a current page number, use it.
else $page $_GET['page'];//If there is no page number, set one!
$total_number_of_items 0;//Count the total number of items in the xml feed
$items_per_page 10;//Set the number of items displayed per page
$counter 0;
function 
myRecordCounter($record)
{
global 
$total_number_of_items;
$total_number_of_items++;// increment for each record in the feed
}
function 
myRecordHandler($item)
{
global 
$page;
global 
$items_per_page;
global 
$counter;
$counter++;
// return false whilst parsing items on previous pages
if ($counter < (($page-1)*$items_per_page)) return false;
//Enter the items to be displayed here as normal
echo "
<tr>
    <td align=\"center\" width=\"200\" height=\"150\">
        <a href='"
.$item["PRODUCTURL"]."'><img src='".$item["IMAGEURL"]."' height='110' width='150' style='border-style: none'></a>
    </td>
    <td width=\"410\" height=\"150\">
        <p>
        <strong>Hotels - hotel:</strong> <a href='"
.$item["PRODUCTURL"]."'><strong>".$item["NAME"]."</strong></a>
        </p>
        <br />
        <p>
        <a href='"
.$item["PRODUCTURL"]."'><strong>".$item["PRICE"]."".$item["CURRENCY"]."</strong> <em>per night</em></a>
        <br />
        </p>
        <br />
        <p>
        "
.$item["DESCRIPTION"]."
        </p>
    </td>
</tr>
<tr>
    <td align=\"center\" colspan=\"2\">
    <span class=\"content-text-bold\">- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</span>
    </td>
</tr>"
;
// return true if counter reaches current page * items on each page
return ($counter == ($page*$items_per_page));
}
//Print the table head tag
echo "<table class=\"content-text\" width=\"610\" border=\"0\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\">";
//Parse the xml feeds
MagicParser_parse("my_xml_feed_url_is_here","myRecordCounter");
MagicParser_parse("my_xml_feed_url_is_here","myRecordHandler","xml|PRODUCTS/PRODUCT/");
//Print the table foot tag
echo "</table>";
$total_pages_count = ($total_number_of_items/$items_per_page);//Calculate the number of pages. Divide the total number of items by the number of items per page.
$total_number_of_pages number_format($total_pages_count0);//Format the total number of pages so that decimals are not displayed
// display link to next page
echo"<p>";
//Display the current page number and the total number of pages
echo"<h1 align=\"center\">PAGE $page of $total_number_of_pages</h1>";
    if (
$page==1){
    
//If the page number is 1 only display the Page 2 link
    
echo "<h1 align=\"center\"><a href='?page=".($page+1)."'>PAGE ".($page+1)." &gt;&gt;</a></h1>";
    }
    else{
    
//If the page number is 2 or higher, display the previous page number and the next page number links
    
echo"<h1 align=\"center\"><a href='?page=".($page-1)."'>&lt;&lt; PAGE ".($page-1)."</a> | <a href='?page=".($page+1)."'>PAGE ".($page+1)." &gt;&gt;</a></h1>";
    }
echo
"</p>";
?>

Submitted by support on Thu, 2006-05-04 14:32

Hi there,

Yes sorry about that - I've spotted the bug in my example code. The following line:

if ($counter < (($page-1)*$items_per_page)) return false;

should be:

if ($counter <= (($page-1)*$items_per_page)) return false;

I would also recommend that you provide your format string for the first call to MagicParser_parse() when you're counting the records, as this will save the autodetection from being carried out, in other worde just change your code where you call the parse function to this:

//Parse the xml feeds
MagicParser_parse("my_xml_feed_url_is_here","myRecordCounter","xml|PRODUCTS/PRODUCT/");
MagicParser_parse("my_xml_feed_url_is_here","myRecordHandler","xml|PRODUCTS/PRODUCT/");

Cheers!
David.

Submitted by travelfrog on Thu, 2006-05-04 19:57

Great David, That's just what I was looking for.

Here is my corrected code for those who wish to use it.

Note:
The code displays one large table with the table rows being repeated inside the table. You will need to change the xml elements xml|PRODUCTS/PRODUCT/ to whatever your xml elements are and you will need to insert your own table row data to suit the elements that you wish to display. The table is designed to be xhtml compatible, so you will need to alter some of the xhtml tags if it is to be html compatible. Where I have used css styles such as class="content-text", you will need to create your own styles for the display presentation.

<?php
//Get the file MagicParser.php
require $_SERVER['DOCUMENT_ROOT'].'/magic-parser/MagicParser.php';
if(!
$_GET['page'])$page 1;// If there is a current page number, use it.
else $page $_GET['page'];//If there is no page number, set one!
$total_number_of_items 0;//Count the total number of items in the xml feed
$items_per_page 10;//Set the number of items displayed per page
$counter 0;
function 
myRecordCounter($record)
{
global 
$total_number_of_items;
$total_number_of_items++;// increment for each record in the feed
}
function 
myRecordHandler($item)
{
global 
$page;
global 
$items_per_page;
global 
$counter;
$counter++;
// return false whilst parsing items on previous pages
if ($counter <= (($page-1)*$items_per_page)) return false;
//Display the xml items that are to be displayed here as normal
echo "
<tr>
    <td align=\"center\" width=\"200\" height=\"150\">
        <a href='"
.$item["PRODUCTURL"]."'><img src='".$item["IMAGEURL"]."' height='110' width='150' style='border-style: none' alt='hotel image' /></a>
    </td>
    <td width=\"410\" height=\"150\">
        <p>
        <strong>Hotels - hotel:</strong> <a href='"
.$item["PRODUCTURL"]."'><strong>".$item["NAME"]."</strong></a>
        </p>
        <br />
        <p>
        <a href='"
.$item["PRODUCTURL"]."'><strong>".$item["PRICE"]."".$item["CURRENCY"]."</strong> <em>per night</em></a>
        <br />
        </p>
        <br />
        <p>
        "
.$item["DESCRIPTION"]."
        </p>
    </td>
</tr>
<tr>
    <td align=\"center\" colspan=\"2\">
    <span class=\"content-text-bold\">- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</span>
    </td>
</tr>"
;
// return true if counter reaches current page * items on each page
return ($counter == ($page*$items_per_page));
}
//Print the table head tag
echo "<table class=\"content-text\" width=\"610\" border=\"0\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\">";
//Parse the xml feeds
MagicParser_parse("my_xml_feed_url_is_here","myRecordCounter","xml|PRODUCTS/PRODUCT/");
MagicParser_parse("my_xml_feed_url_is_here","myRecordHandler","xml|PRODUCTS/PRODUCT/");
//Print the table foot tag
echo "</table>";
$total_pages_count = ($total_number_of_items/$items_per_page);//Calculate the number of pages. Divide the total number of items by the number of items per page.
$total_number_of_pages number_format($total_pages_count0);//Format the total number of pages so that decimals are not displayed
//Display the current page number and the total number of pages
echo"<h1 align=\"center\">PAGE $page of $total_number_of_pages</h1>";
    if (
$page==1){
    
//If the page number is 1 only display the Page 2 link
    
echo "<h1 align=\"center\"><a href='?page=".($page+1)."'>PAGE ".($page+1)." &gt;&gt;</a></h1>";
    }
    else{
    
//If the page number is 2 or higher, display the previous page number and the next page number links
    
echo"<h1 align=\"center\"><a href='?page=".($page-1)."'>&lt;&lt; PAGE ".($page-1)."</a> | <a href='?page=".($page+1)."'>PAGE ".($page+1)." &gt;&gt;</a></h1>";
    }
?>

Submitted by travelfrog on Thu, 2006-05-04 20:19

David,

Just another thought. Is it possible to display the xml items in a set order such as lowest price first? If so, what would I need to do to the code to achieve this?

Submitted by travelfrog on Wed, 2006-05-10 22:12

Hi David,

Great the pages display the correct number of items. However, I just noticed that the paging script that we have arrived at is actually displaying the last item from the previous page as the first item on a new page. Any ideas on what needs to be altered?

Also, is there any way to order the display of results by the price?

Submitted by support on Thu, 2006-05-11 04:41

Hi,

Would you be able to double check that your paging code is the same as in the following test script. I couldn't spot an error so I just tried it, and it seems to be working correctly. Click here to view the live output from this script:

<?php
  
require("MagicParser.php");
  
$page $_GET["page"];
  if (!
$page$page 1;
  
$items_per_page 3;
  function 
myRecordHandler($item)
  {
    global 
$page;
    global 
$items_per_page;
    global 
$counter;
    
$counter++;
    if (
$counter <= (($page-1)*$items_per_page)) return false;
    print 
"<h2><a href='".$item["LINK"]."'>".$item["TITLE"]."</a></h2>";
    print 
"<p>".$item["DESCRIPTION"]."</p>";
    return (
$counter == ($page*$items_per_page));
  }
  print 
"<h1>BBC News Headlines</h1>";
  
$url "http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml";    
  
MagicParser_parse($url,"myRecordHandler","xml|RSS/CHANNEL/ITEM/");  
  print 
"<a href='?page=".($page+1)."'>Next</a>";
?>

Sorry that I missed your earlier message about sorting by price. For the same reasons that the only way to count the number of records is to parse the entire file, in this scenario, your only option is to read the entire XML document into an array rather than displaying each item, and then sort the array by price, and then display items out of the array as per the current page.

However, as it happens you are reading the entire file anyway in order to get the record count; so that actually means you can achieve this without having to parse the file twice as you are doing at the moment.

Here's an example that will display the BBC News headlines sorted by headline. The code first parses the entire file into an array using the headline as the array key. Next, it uses ksort() to sort the array by key, and finally loops through each item in the array to generate the output. Click here to view the live output from this script:

<?php
  
require("MagicParser.php");
  
$sortedItems = array();
  function 
myRecordHandler($item)
  {
    global 
$sortedItems;
    
$sortedItems[$item["TITLE"]] = $item;
  }
  
$url "http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml";    
  
MagicParser_parse($url,"myRecordHandler","xml|RSS/CHANNEL/ITEM/");  
  
ksort($sortedItems);
  print 
"<h1>BBC News Headlines</h1>";  
  foreach(
$sortedItems as $item)
  {
    print 
"<h2><a href='".$item["LINK"]."'>".$item["TITLE"]."</a></h2>";
    print 
"<p>".$item["DESCRIPTION"]."</p>";
  }
?>

Hope this helps!
Cheers,
David.

Submitted by travelfrog on Fri, 2006-05-12 22:52

Hi David,

I managed to get the data to sort by price. However, when I have tried to page the results, the sorting by price has become unsorted. Can you please point me in the right direction as to where I am going wrong.

Here is what I have so far:-

<?php
require $_SERVER['DOCUMENT_ROOT'].'/magic-parser/MagicParser.php';
$total_number_of_items 0;//Count the total number of items in the XML feed
$sortedItems = array();
if(!
$_GET['page'])$page 1;// If there is a current page number, use it.
else $page $_GET['page'];//If there is no page number, set one!
$items_per_page 10;//Set the number of items to be displayed per page
$counter 0;
function 
myRecordCounter($record)
{
global 
$total_number_of_items;
$total_number_of_items++;// increment for each record in the feed
}
function 
myRecordHandler($item)
{
global 
$sortedItems;
global 
$page;
global 
$items_per_page;
global 
$counter;
$counter++;
// return false whilst parsing items on previous pages
if ($counter <= (($page-1)*$items_per_page)) return false;
$sortedItems[$item["PRICE"]] = $item;
// return true if counter reaches current page * items on each page
return ($counter == ($page*$items_per_page));
}
$url "my_url_is_here";
MagicParser_parse($url,"myRecordCounter","xml|PRODUCTS/PRODUCT/");
MagicParser_parse($url,"myRecordHandler","xml|PRODUCTS/PRODUCT/");
ksort($sortedItems);
echo
"<br /><h1 align=\"center\">Accommodation</h1>";
echo 
"<table class=\"content-text\" width=\"610\" border=\"0\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\">";
foreach(
$sortedItems as $item)
{
echo 
"<tr>
    <td align=\"center\" width=\"200\" height=\"150\">
        <a href='"
.$item["PRODUCTURL"]."'><img src='".$item["IMAGEURL"]."' style='border-style: none' alt='Hotel Accommodation' /></a>
    </td>
    <td width=\"410\" height=\"150\">
        <p>
        <strong>Hostelbookers:</strong><br />
        <a href='"
.$item["PRODUCTURL"]."'><strong>".$item["NAME"]."<br />".$item["FIELDS/FIELD/VALUE"].", ".$item["FIELDS/FIELD/VALUE@1"]."</strong></a>
        </p>
        <br />
        <p>
        <a href='"
.$item["PRODUCTURL"]."'><em>from:</em><strong> ".$item["PRICE"]."".$item["CURRENCY"]."</strong> <em>per night</em></a>
        <br />
        </p>
        <br />
        <p>
        "
.$item["DESCRIPTION"]."
        </p>
    </td>
</tr>
<tr>
    <td align=\"center\" colspan=\"2\">
    <span class=\"content-text-bold\">- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</span>
    </td>
</tr>"
;
  }
echo 
"</table>"
$total_pages_count = ($total_number_of_items/$items_per_page);//Calculate the number of pages. Divide the total number of items by the number of items per page.
$total_number_of_pages number_format($total_pages_count0);//Format the total number of pages so that decimals are not displayed
//Display the current page number and the total number of pages
echo"<h1 align=\"center\">PAGE $page of $total_number_of_pages</h1>";
if (
$page==1){
//If the page number is 1 only display the Page 2 link
echo "<h1 align=\"center\"><a href='?page=".($page+1)."'>PAGE ".($page+1)." &gt;&gt;</a></h1>";
}else{
//If the page number is 2 or higher, display the previous page number and the next page number links
echo"<h1 align=\"center\"><a href='?page=".($page-1)."'>&lt;&lt; PAGE ".($page-1)."</a> | <a href='?page=".($page+1)."'>PAGE ".($page+1)." &gt;&gt;</a></h1>";
}
?>

Submitted by travelfrog on Sat, 2006-05-13 23:28

Hi David,

I thought that I would clarify exactly what I am trying to do as it seems that I keep posting here.
I can paginate my xml feed, but the items are all mixed up as I wish to sort them by Price.
I can sort the feed items to display by Price, but the page displays 100 items.
I cannot get the two to work together to do what I want.

I have an xml feed with 100 items.
1. I wish to sort the items by Price.
2. I wish to display only 10 items per page.
3. I wish to display pagination as below.
<<PREVIOUS 1|2|3|4|5|6|7|8|9|10 NEXT>>

It is probably very simple to combine the two, but I just cannot get my head around it.

Submitted by support on Mon, 2006-05-15 16:42

Hi,

I've tried to fixup your last modified version to apply the paging to the sorted set. Please note that I haven't been able to test this so it might not be quite there, but should give you a basis to work from.

What you need to do is combine the counter and the sorter into one parse; as all records have to be read in order to do the sort - there is no getting away from that fact because of the serial nature of XML.

Hope this helps...
Cheers,
David.

<?php
require $_SERVER['DOCUMENT_ROOT'].'/magic-parser/MagicParser.php';
$total_number_of_items 0;//Count the total number of items in the XML feed
$sortedItems = array();
if(!
$_GET['page'])$page 1;// If there is a current page number, use it.
else $page $_GET['page'];//If there is no page number, set one!
$items_per_page 10;//Set the number of items to be displayed per page
$counter 0;
// COUNT AND SORT AT THE SAME TIME
function myRecordCounter($item)
{
global 
$sortedItems;
global 
$total_number_of_items;
$total_number_of_items++;// increment for each record in the feed
$sortedItems[$item["PRICE"]] = $item;
}
function 
buildDisplayItemsArray($item)
{
global 
$displayItems;
global 
$page;
global 
$items_per_page;
global 
$counter;
$counter++;
// return false whilst parsing items on previous pages
if ($counter <= (($page-1)*$items_per_page)) return false;
$displayItems[] = $item;
// return true if counter reaches current page * items on each page
return ($counter == ($page*$items_per_page));
}
$url "my_url_is_here";
MagicParser_parse($url,"myRecordCounter","xml|PRODUCTS/PRODUCT/");
ksort($sortedItems);
// NOW BUILD ARRAY OF THE ONES TO BE DISPLAYED
foreach($sortedItems as $item)
{
  
buildDisplayItemsArray($item);
}
// FINALLY DISPLAY EACH OF THE DISPLAY ITEMS
echo"<br /><h1 align=\"center\">Accommodation</h1>";
echo 
"<table class=\"content-text\" width=\"610\" border=\"0\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\">";
foreach(
$displayItems as $item)
{
echo 
"<tr>
    <td align=\"center\" width=\"200\" height=\"150\">
        <a href='"
.$item["PRODUCTURL"]."'><img src='".$item["IMAGEURL"]."' style='border-style: none' alt='Hotel Accommodation' /></a>
    </td>
    <td width=\"410\" height=\"150\">
        <p>
        <strong>Hostelbookers:</strong><br />
        <a href='"
.$item["PRODUCTURL"]."'><strong>".$item["NAME"]."<br />".$item["FIELDS/FIELD/VALUE"].", ".$item["FIELDS/FIELD/VALUE@1"]."</strong></a>
        </p>
        <br />
        <p>
        <a href='"
.$item["PRODUCTURL"]."'><em>from:</em><strong> ".$item["PRICE"]."".$item["CURRENCY"]."</strong> <em>per night</em></a>
        <br />
        </p>
        <br />
        <p>
        "
.$item["DESCRIPTION"]."
        </p>
    </td>
</tr>
<tr>
    <td align=\"center\" colspan=\"2\">
    <span class=\"content-text-bold\">- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</span>
    </td>
</tr>"
;
  }
echo 
"</table>";
$total_pages_count = ($total_number_of_items/$items_per_page);//Calculate the number of pages. Divide the total number of items by the number of items per page.
$total_number_of_pages number_format($total_pages_count0);//Format the total number of pages so that decimals are not displayed
//Display the current page number and the total number of pages
echo"<h1 align=\"center\">PAGE $page of $total_number_of_pages</h1>";
if (
$page==1){
//If the page number is 1 only display the Page 2 link
echo "<h1 align=\"center\"><a href='?page=".($page+1)."'>PAGE ".($page+1)." &gt;&gt;</a></h1>";
}else{
//If the page number is 2 or higher, display the previous page number and the next page number links
echo"<h1 align=\"center\"><a href='?page=".($page-1)."'>&lt;&lt; PAGE ".($page-1)."</a> | <a href='?page=".($page+1)."'>PAGE ".($page+1)." &gt;&gt;</a></h1>";
}
?>

Submitted by travelfrog on Mon, 2006-05-15 17:31

Hi Dave,

Thank you for the reply.
The script is better, but is still not working quite right.

The items are now being displayed sorted by price and can be paged, but approx 57 products are being displayed per page instead of 10 and each page seems to start with the following 10th product.

Instead of ten pages with ten products, I now have five pages showing 57 products and page 6 shows 7 products.

Any ideas where the problem lies?

Submitted by support on Mon, 2006-05-15 18:02

Ah yes, the way I implemented this for you I simlated the record handler function mechanism, but the loop that called the function to build the display items array was not breaking out when the builder function returns true...

Instead of this:

// NOW BUILD ARRAY OF THE ONES TO BE DISPLAYED
foreach($sortedItems as $item)
{
  buildDisplayItemsArray($item);
}

...try...

// NOW BUILD ARRAY OF THE ONES TO BE DISPLAYED
foreach($sortedItems as $item)
{
  if (buildDisplayItemsArray($item)) break;
}

That should do the trick.

Submitted by travelfrog on Mon, 2006-05-15 21:33

Hi Dave,

Thank you again for the quick reply.
The modification has now paged the products at 10 per page. However, the pagination script is displaying the correct amount of 10 pages, but there are only 6 pages when the next page links are clicked. In order for you to help me achieve the display of 10 results per page over 10 pages, here is the feed that I am trying to parse.

http://pf.tradedoubler.com/pf/pf?a=1208519&categoryId=168&programs=31820&description=(hotel)&maxResults=100&firstResult=0&oe=

Submitted by travelfrog on Mon, 2006-05-15 22:22

Hi Dave,

Here is the latest script that I have.
I have commented the various parts to make it more reader friendly. I look forward to your help on resolving this problem. I would guess that most users of MagicParser will be trying to display xml/rss feeds using MagicParser and I believe that once sorted out, this will be a very useful script to provide as an example of a sorted and paged xml feed.

After further investigation, for some reason, items that have the exact same price are not being displayed. For example, there are 3 items with a price of 115.00 and only one item is being displayed in the paginated results.

<?php
require $_SERVER['DOCUMENT_ROOT'].'/magic-parser/MagicParser.php';
//////////////////////////////////////////////////////////////////////////////////////
//SET THE MAIN SCRIPT VARIABLES
$url "http://pf.tradedoubler.com/pf/pf?a=1208519&categoryId=168&programs=31820&description=(hotel)&maxResults=100&firstResult=0&oe=";
$total_number_of_items 0;//Count the total number of items in the XML feed
$sortedItems = array();//Store the sorted items in an array
if(!$_GET['page'])$page 1;// If there is a current page number, use it.
else $page $_GET['page'];//If there is no page number, set one!
$items_per_page 10;//Set the number of items to be displayed per page
$counter 0;
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//COUNT AND SORT THE ITEMS IN ONE FUNCTION
function SortandCountItems($item)
{
    global 
$sortedItems;
    
$sortedItems[$item["PRICE"]] = $item;//sort the items by lowest price
    
global $total_number_of_items;
    
$total_number_of_items++;// increment for each record in the feed
}
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//FUNCTION TO AID PAGINATION OF THE ITEMS
function buildPaginationItemsArray($item)
{
    global 
$displayItems;
    global 
$page;
    global 
$items_per_page;
    global 
$counter;
    
$counter++;
    
// return false whilst parsing items on previous pages
    
if ($counter <= (($page-1)*$items_per_page)) return false;
    
$displayItems[] = $item;
    
// return true if counter reaches current page * items on each page
    
return ($counter == ($page*$items_per_page));
}
//////////////////////////////////////////////////////////////////////////////////////
//PARSE THE FUNCTION SortandCountItems
MagicParser_parse($url,"SortandCountItems","xml|PRODUCTS/PRODUCT/");
//SORT THE ARRAY sortedItems
ksort($sortedItems);
//////////////////////////////////////////////////////////////////////////////////////
//NOW BUILD AN ARRAY OF THE ITEMS TO BE DISPLAYED
foreach($sortedItems as $item)
{
  if(
buildPaginationItemsArray($item)) break;
}
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//DISPLAY THE PAGE TITLE
echo"<br /><h1 align=\"center\">Accommodation</h1>";
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//DISPLAY THE TABLE HEADER TAG
echo "<table class=\"content-text\" width=\"610\" border=\"0\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\">";
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//DISPLAY THE ITEMS IN FORMATTED TABLE ROWS
foreach($displayItems as $item)
{
echo 
"<tr>
    <td align=\"center\" width=\"200\" height=\"150\">
        <a href='"
.$item["PRODUCTURL"]."'><img src='".$item["IMAGEURL"]."' height='110' width='150' style='border-style: none' alt='Hotel Accommodation' /></a>
    </td>
    <td width=\"410\" height=\"150\">
        <p>
        <strong>Hotel:</strong><br />
        <a href='"
.$item["PRODUCTURL"]."'><strong>".$item["NAME"]."<br />".$item["FIELDS/FIELD/VALUE"].", ".$item["FIELDS/FIELD/VALUE@1"]."</strong></a>
        </p>
        <br />
        <p>
        <a href='"
.$item["PRODUCTURL"]."'><em>from:</em><strong> ".$item["PRICE"]."".$item["CURRENCY"]."</strong> <em>per night</em></a>
        <br />
        </p>
        <br />
        <p>
        "
.$item["DESCRIPTION"]."
        </p>
    </td>
</tr>
<tr>
    <td align=\"center\" colspan=\"2\">
    <span class=\"content-text-bold\">- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</span>
    </td>
</tr>"
;
  }
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//DISPLAY THE TABLE FOOTER TAG
echo "</table>";
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//DISPLAY THE PAGINATION example:
//      PAGE 4 of 10
//<<PREVIOUS 3 | 5 NEXT>>
$total_pages_count = ($total_number_of_items/$items_per_page);//Calculate the number of pages. Divide the total number of items by the number of items per page.
$total_number_of_pages number_format($total_pages_count0);//Format the total number of pages so that decimals are not displayed
//Display the current page number and the total number of pages
echo"<h1 align=\"center\">PAGE $page of $total_number_of_pages</h1>";
if (
$page==1){
//If the page number is 1 only display the Page 2 link
echo "<h1 align=\"center\"><a href='?page=".($page+1)."'>PAGE ".($page+1)." &gt;&gt;</a></h1>";
}else{
//If the page number is 2 or higher, display the previous page number and the next page number links
echo"<h1 align=\"center\"><a href='?page=".($page-1)."'>&lt;&lt; PAGE ".($page-1)."</a> | <a href='?page=".($page+1)."'>PAGE ".($page+1)." &gt;&gt;</a></h1>";
}
//////////////////////////////////////////////////////////////////////////////////////
?>

Submitted by travelfrog on Tue, 2006-05-16 18:49

Hi David,

Any chance that you could please have a look at this?

I have done a little more investigation.
The current script does not currently display all of the items and if any of the prices are the same, it only displays one of them. To do a simple test, I changed the price for the tdproductid which should all be unique. Upon testing this, all of the items were returned in the paging and all 10 pages had 10 items displayed.

How can I get the pages to display all of the items by price, even if they are duplicated prices. Can I display the items using the tdproductid and the price together?

Submitted by support on Wed, 2006-05-17 04:16

Hiya,

The reason there is only one item with the same price is because during the count and sort process; the $sortedItems array is constructed using the price as the key, so there will only ever be one item with any given price.

To resolve this, independent arrays need to be constructed for every price, and then the price arrays merged before the script continues. To start with, the count and sort function needs to be as follows (PHP tags used for clarity - these are actually parts of the larger script above):

<?php
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//COUNT AND SORT THE ITEMS IN ONE FUNCTION
function SortandCountItems($item)
{
    global 
$sortedItems;
    
$sortedItems[$item["PRICE"]][] = $item;//sort the items by lowest price
    
global $total_number_of_items;
    
$total_number_of_items++;// increment for each record in the feed
}
?>

All that's been added there is the [] after $sortedItems[$item["PRICE"]]. What this does is create an array of every $item with the same price rather than just storing 1 item per price.

Then, more code is needed to sort the array. Instead of just:

<?php
//SORT THE ARRAY sortedItems
ksort($sortedItems);
?>

Change this to:

<?php
//SORT THE ARRAY sortedItems
ksort($sortedItems);
foreach(
$sortedItems as $samePriceItems)
{
  foreach(
$samePriceItems as $item)
  {
    
$newSortedItems[] = $item;
  }
}
$sortedItems $newSortedItems;
?>

If you follow through the code above you'll see how it works; i) sort the $sortedItems array as before; ii) loop through each item, which itself contains an array of items at the same price, iii) add each item to the $newSortedItems array, and finally iv) copy $newSortedItems back to $sortedItems for use in th rest of the code.

Hope this helps,
David.