Pagination with XML content

Hello all, I did the XML CMS tutorial on site points website.

Great tutorial.

How can I implement pagination to the results pulled in from XML? Id also like to add next and previous buttons to browse through a collection of XML articles. How can I achieve this? Any help would be much appreciated. The code from index.php that draws in the XML is below:


<?php

function extractText($array){
	if(count($array) <= 1){
		//we only have one tag to process!
		for ($i = 0; $i<count($array); $i++){
			$node = $array[$i];
			$value = $node->get_content();
		}
		return $value;
	} 
	
}	
?>

<?php
$dh = opendir('./xml/');

$fileCount = 0;
while ($file = readdir($dh) and $fileCount < 5){
	if (eregi("^..?$", $file)) {
		continue;
	}
	$open = "./xml/".$file;
	$xml = domxml_open_file($open);

	//we need to pull out all the things from this file that we will need to 
	//build our links
	$root = $xml->root();
	$stat_array = $root->get_elements_by_tagname("status");
	$status = extractText($stat_array);
	
	$ab_array = $root->get_elements_by_tagname("abstract");
	$abstract = extractText($ab_array);

	$h_array = $root->get_elements_by_tagname("headline");
	$headline = extractText($h_array);

	if ($status != "live"){
		continue;
	}
	echo "<tr valign=top><td>";
	echo "<a href=\\"showArticle.php?file=".$file . "\\">".$headline . "</a><br>";
	echo $abstract;
	echo "</td></tr>";
	
	$fileCount++;
}
?>

anyone? Im assuming that I would make a conditional after the while loop, or inside it(?) and id use the

$filecount as limit.

maybe something like this:
if ($filecount > 5)

is my thinking correct, and how would I go about sending the articles not displayed to maybe a results page?

Have you figured this out yet?
If so can you share with the rest of us?

I belive I’m going in the correct direction but what I have so far shows me 5 items from my xml. I need to know how to create the next page with the five next items. btw: I’m reading the posts from last to first.

//read from bev.xml
$file = 'xml/bev.xml';
$xml = simplexml_load_file($file);

$limit = 5;
$page = $_GET['page'];
$c = 1;

$i = count($xml->messages)-1;
for($x=$i;$x>=0;$x--)
if (empty($page) )
{
  if ($c > 0 && $c <= $limit)
  {	
    //write to page
    echo
      $xml->messages[$x]->$vdate.'<br /><p>'
      .$xml->messages[$x]->msgpost.'<hr></p>';
      $c++;
  }
}

my xml

<sayings>
  <message>
    <vdate></vdate>
    <msgpost></msgpost>
  </message>
</sayings>

Am I even going in the right direction?


<?php
class Pagination {
	
	protected
	
	/*
	* Configuration defaults
	*/
	$_arrConfig = array(
		'limit'=>10
		,'page'=>1
		,'basePath'=>'#'
		,'label'=>'Items'
		,'visiblePages'=>5
		,'pageFlag'=>'{page}'
	)
	
	/*
	* Data to be passed to template
	*/
	,$_arrTemplateData = array()
	
	/*
	* function to pass resolved offset and limit
	*/
	,$_onPaginate
	
	/*
	* extra arguments to pass to to pagination callback 
	* such as data source or db connection
	*/
	,$_arrArgs;
	
	public function __construct($onPaginate,$arrConfig=array(),$arrArgs=array()) {
	
		$this->_onPaginate = $onPaginate;
		$this->_arrArgs = $arrArgs;
	
		foreach($arrConfig as $strKey=>$mixValue) {
			if(array_key_exists($strKey,$this->_arrConfig)) {
				$this->_arrConfig[$strKey] = $mixValue;
			}
		}
	}
	
	public function paginate() {
	
		/*
		* Calculate page offset 
		*/
		$intOffset = ($this->_arrConfig['page']-1)*$this->_arrConfig['limit'];
		
		/*
		* Paginate and get number of found rows 
		*/
		$intFoundRows = call_user_func_array($this->_onPaginate,array_merge(array($intOffset,$this->_arrConfig['limit']),$this->_arrArgs));
		
		/*
		* Assign template data 
		*/
		$this->_arrTemplateData['limit'] = $this->_arrConfig['limit'];
		$this->_arrTemplateData['page'] = $this->_arrConfig['page'];
		$this->_arrTemplateData['offset'] = $intOffset;
		$this->_arrTemplateData['found_rows'] = $intFoundRows;
		$this->_arrTemplateData['total_pages'] = $intFoundRows < $this->_arrConfig['limit']?1:ceil($intFoundRows/$this->_arrConfig['limit']);
		$this->_arrTemplateData['visible_pages'] = $this->_arrConfig['visiblePages'];
		$this->_arrTemplateData['base_path'] = $this->_arrConfig['basePath'];
		$this->_arrTemplateData['label'] = $this->_arrConfig['label'];
		$this->_arrTemplateData['page_flag'] = $this->_arrConfig['pageFlag'];
		
		/*
		* Return the pagination template 
		*/
		return $this->display();
	}
	
	public function display() {
		extract($this->_arrTemplateData);
		
		if($total_pages <= $visible_pages) {
    		$page_start = 1;
    		$page_end = $total_pages;
		} else if($page <= ceil($visible_pages/2)) {
    		$page_start = 1;
    		$page_end = $visible_pages;
		} else if($page > ($total_pages - ceil($visible_pages/2))) {
    		$page_start = $total_pages - (ceil(($visible_pages/2)*2)-1);
    		$page_end = $total_pages;
		} else {
    		$page_start = $page-(floor($visible_pages/2));
    		$page_end = $page+(floor($visible_pages/2));
		}
		
		$return = sprintf(
   			'<div class="summary"><p class="pages">&#37;u %s</p><p class="total">%u %s</p></div>'
    		,$total_pages
    		,$total_pages == 1?'Page':'Pages'
    		,$found_rows
    		,$found_rows == 1?$label:$label
		);
		
		$return.= sprintf('<ul class="pagination">');
		$return.= sprintf(
    		'<li class="first">%s%s%s</li>'
    		,$page == 1?'':sprintf('<a href="%s">',str_replace($page_flag,1,$base_path))
    		,'First'
    		,$page == 1?'':'</a>'
		);    
		$return.= sprintf(
    		'<li class="previous">%s%s%s</li>'
   		 	,$page == 1?'':sprintf('<a href="%s">',str_replace($page_flag,($page-1),$base_path))
    		,'Previous'
    		,$page == 1?'':'</a>'
		);
		foreach(range($page_start,$page_end,1) as $i) {
    		$return.= sprintf(
        		'<li%s>%s%s%s</li>'
        		,$page == $i?' class="current"':''
        		,$page == $i?'':sprintf('<a href="%s">',str_replace($page_flag,$i,$base_path))
        		,$i
        		,$page == $i?'':'</a>'
    		);
		}
		$return.= sprintf(
			'<li class="next">%s%s%s</li>'
			,$page == $total_pages?'':sprintf('<a href="%s">',str_replace($page_flag,($page+1),$base_path))
    		,'Next'
    		,$page == $total_pages?'':'</a>'
		);
		$return.= sprintf(
    		'<li class="last">%s%s%s</li>'
    		,$page == $total_pages?'':sprintf('<a href="%s">',str_replace($page_flag,$total_pages,$base_path))
    		,'Last'
    		,$page == $total_pages?'':'</a>'
		);
		$return.= sprintf('</ul>');
		
		return $return;
		
	}

}

class Action {

	private $_objXML;
	private $_arrMessages = array();

	public function __construct() {
		
		$this->_objXML = simplexml_load_string(
'<sayings>
  <message>
    <vdate>1</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>2</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>3</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>4</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>5</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>6</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>7</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>8</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>9</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>10</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>11</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>12</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>13</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
</sayings>');
		
	}

	public function paginate($offset,$limit) {
	
		$arrMessages = $this->_objXML->xpath('message');
		
		if(isset($arrMessages[$offset])) {
			for($i=0;$i<$limit;$i++) {
			
				if(!isset($arrMessages[($i+$offset)])) break;
			
				$this->_arrMessages[] = array(
					'vdate'=>(string) $arrMessages[($i+$offset)]->vdate
					,'msgpost'=>(string) $arrMessages[($i+$offset)]->msgpost
				);
			}
		}
		
		// return number of total found rows
		return count($arrMessages);
	
	}
	
	public function getMessages() {
		return $this->_arrMessages;
	}

}

$action = new Action();

$func = create_function('$offset,$limit,$action','return $action->paginate($offset,$limit);');
$pg = new Pagination($func,array(
	'basePath'=>$_SERVER['PHP_SELF'].'?p={replace_me_with_page}'
	,'pageFlag'=>'{replace_me_with_page}'
	,'label'=>'Messages'
	,'limit'=>5
	,'page'=>isset($_GET['p']) && is_numeric($_GET['p']) && $_GET['p'] != 0?$_GET['p']:1
	,'visiblePages'=>5
),array($action));
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8">
	<title>Untitled</title>
	<style type="text/css">
	.pagination {
		text-align: center;
	}
	.pagination li {
		display: inline-block;
	}
	*+html .pagination li {
		display: inline;
	}
	* html .pagination li {
		display: inline;
	}
	</style>
</head>
<body>
	<?php echo $pg->paginate(); ?>
	
	<?php 
	if($action->getMessages()) {
		echo '<ol>';
		foreach($action->getMessages() as $arrMessage) {
			printf(
				'<li>
					<p>%s</p>
					<p>%s</p>
				 </li>'
				 ,$arrMessage['vdate']
			 	,$arrMessage['msgpost']
			);
		} 
		echo '</ol>';
	} else {
		echo "<p>No messages available</p>";
	}?>
</body>
</html>

The logic doesn’t change just the data source.

you created a class (I don’t really have a good grasp of classes) with my xml structure in it (although vdate is a date field in mine). Can I just link to my .xml document?

You would replace simplexml_load_string with simplexml_load_file. I just used a string to keep everything in a single file so that you can copy and paste to see it work.

oddz
love love love you.

Can this be set to post most recent entries first?

Also when I pointed to my .xml file…when the page is viewed it says “No messages available”
Is this because my vdate is a Date field and you used as a count (1, 2, 3, ect.)?

I got my xml to work…

I’m trying to figure out how this works so I can…

  1. reverse order
  2. put navigation at bottom and top
  3. remove “# pages” and “# Messages”
  4. place spaces between “First”, “Previous”, page numbers, “Next”, and “Last”

Is there any documentation on this pagination class?

You can order the messages using a XSLT transformation to place them in ascending or descending order. I added a config property for removing the top message and page header. I than dumped the pagination interface twice to place it at the bottom and top. You can use CSS to place spaces between the various pagination HTML element.


<?php
class Pagination {
	
	protected
	
	/*
	* Configuration defaults
	*/
	$_arrConfig = array(
		'limit'=>10
		,'page'=>1
		,'basePath'=>'#'
		,'label'=>'Items'
		,'visiblePages'=>5
		,'pageFlag'=>'{page}'
		,'display_pages'=>1
		,'display_entity'=>1
	)
	
	/*
	* Data to be passed to template
	*/
	,$_arrTemplateData = array()
	
	/*
	* function to pass resolved offset and limit
	*/
	,$_onPaginate
	
	/*
	* extra arguments to pass to to pagination callback 
	* such as data source or db connection
	*/
	,$_arrArgs;
	
	public function __construct($onPaginate,$arrConfig=array(),$arrArgs=array()) {
	
		$this->_onPaginate = $onPaginate;
		$this->_arrArgs = $arrArgs;
	
		foreach($arrConfig as $strKey=>$mixValue) {
			if(array_key_exists($strKey,$this->_arrConfig)) {
				$this->_arrConfig[$strKey] = $mixValue;
			}
		}
	}
	
	public function paginate() {
	
		/*
		* Calculate page offset 
		*/
		$intOffset = ($this->_arrConfig['page']-1)*$this->_arrConfig['limit'];
		
		/*
		* Paginate and get number of found rows 
		*/
		$intFoundRows = call_user_func_array($this->_onPaginate,array_merge(array($intOffset,$this->_arrConfig['limit']),$this->_arrArgs));
		
		/*
		* Assign template data 
		*/
		$this->_arrTemplateData['limit'] = $this->_arrConfig['limit'];
		$this->_arrTemplateData['page'] = $this->_arrConfig['page'];
		$this->_arrTemplateData['offset'] = $intOffset;
		$this->_arrTemplateData['found_rows'] = $intFoundRows;
		$this->_arrTemplateData['total_pages'] = $intFoundRows < $this->_arrConfig['limit']?1:ceil($intFoundRows/$this->_arrConfig['limit']);
		$this->_arrTemplateData['visible_pages'] = $this->_arrConfig['visiblePages'];
		$this->_arrTemplateData['base_path'] = $this->_arrConfig['basePath'];
		$this->_arrTemplateData['label'] = $this->_arrConfig['label'];
		$this->_arrTemplateData['page_flag'] = $this->_arrConfig['pageFlag'];
		$this->_arrTemplateData['display_pages'] = $this->_arrConfig['display_pages'];
		$this->_arrTemplateData['display_entity'] = $this->_arrConfig['display_entity'];
		
		/*
		* Return the pagination template 
		*/
		return $this->display();
	}
	
	public function display() {
		extract($this->_arrTemplateData);
		
		if($total_pages <= $visible_pages) {
    		$page_start = 1;
    		$page_end = $total_pages;
		} else if($page <= ceil($visible_pages/2)) {
    		$page_start = 1;
    		$page_end = $visible_pages;
		} else if($page > ($total_pages - ceil($visible_pages/2))) {
    		$page_start = $total_pages - (ceil(($visible_pages/2)*2)-1);
    		$page_end = $total_pages;
		} else {
    		$page_start = $page-(floor($visible_pages/2));
    		$page_end = $page+(floor($visible_pages/2));
		}
		
		$return='';
		
		if($display_pages && $display_entity) {
		$return.= sprintf(
   			'<div class="summary"><p class="pages">&#37;u %s</p><p class="total">%u %s</p></div>'
    		,$total_pages
    		,$total_pages == 1?'Page':'Pages'
    		,$found_rows
    		,$found_rows == 1?$label:$label
		);
		}
		
		$return.= sprintf('<ul class="pagination">');
		$return.= sprintf(
    		'<li class="first">%s%s%s</li>'
    		,$page == 1?'':sprintf('<a href="%s">',str_replace($page_flag,1,$base_path))
    		,'First'
    		,$page == 1?'':'</a>'
		);    
		$return.= sprintf(
    		'<li class="previous">%s%s%s</li>'
   		 	,$page == 1?'':sprintf('<a href="%s">',str_replace($page_flag,($page-1),$base_path))
    		,'Previous'
    		,$page == 1?'':'</a>'
		);
		foreach(range($page_start,$page_end,1) as $i) {
    		$return.= sprintf(
        		'<li%s>%s%s%s</li>'
        		,$page == $i?' class="current"':''
        		,$page == $i?'':sprintf('<a href="%s">',str_replace($page_flag,$i,$base_path))
        		,$i
        		,$page == $i?'':'</a>'
    		);
		}
		$return.= sprintf(
			'<li class="next">%s%s%s</li>'
			,$page == $total_pages?'':sprintf('<a href="%s">',str_replace($page_flag,($page+1),$base_path))
    		,'Next'
    		,$page == $total_pages?'':'</a>'
		);
		$return.= sprintf(
    		'<li class="last">%s%s%s</li>'
    		,$page == $total_pages?'':sprintf('<a href="%s">',str_replace($page_flag,$total_pages,$base_path))
    		,'Last'
    		,$page == $total_pages?'':'</a>'
		);
		$return.= sprintf('</ul>');
		
		return $return;
		
	}
	/*
	* Get current page
	*/
	public function getPage() {
		return $this->_arrConfig['page'];
	}

}

class Action {

	private $_objXML;
	private $_boolAscending = true;
	private $_arrMessages = array();

	public function __construct($boolAscending=true) {
	
		/*
		* Set ordering
		*/
		$this->_boolAscending = $boolAscending;
		
		$strXML =
'<sayings>
  <message>
    <vdate>2010-06-01 00:48:21</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>2010-06-09 00:48:21</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>2010-02-09 00:48:21</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>2010-02-09 00:48:21</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
  <message>
    <vdate>2009-06-09 00:48:21</vdate>
    <msgpost>xxxxx</msgpost>
  </message>
</sayings>';

		/*
		* transform timestamps
		*/
		$objXML = simplexml_load_string($strXML);
		foreach($objXML->children() as $message) {
			$message->vdate = strtotime((string) $message->vdate);
		}


		$strStyle =
'<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions">

	<xsl:template match="/">
		<xsl:call-template name="content">
		</xsl:call-template>
	</xsl:template>
	
	<xsl:template name="content">
		<sayings>
		<xsl:for-each select="/sayings/message">
			<xsl:sort select="vdate" data-type="number" order="'.($this->_boolAscending?'ascending':'descending').'"/>
			<message>
				<vdate><xsl:value-of select="vdate"/></vdate>
				<msgpost><xsl:value-of select="msgpost"/></msgpost>
			</message>
		</xsl:for-each>
		</sayings>
	</xsl:template>
	
</xsl:stylesheet>';
		
		
		/*
		* Load message DOM document 
		*/
		$objMessage = new DOMDocument();
		$objMessage->loadXML($objXML->asXML());
		
		/*
		* Load transform DOM document 
		*/
		$objStylesheet = new DOMDocument();
		$objStylesheet->loadXML($strStyle);
		
		/*
		* Create XSLT processor ansd set stylesheet 
		*/
		$objXSLT = new XSLTProcessor(); 
		$objXSLT->importStylesheet($objStylesheet);
		
		/*
		* apply transform
		*/
		$this->_objXML = simplexml_load_string($objXSLT->transformToXML($objMessage));

		
	}

	public function paginate($offset,$limit) {
	
		$arrMessages = $this->_objXML->xpath('message');
		
		if(isset($arrMessages[$offset])) {
			for($i=0;$i<$limit;$i++) {
			
				if(!isset($arrMessages[($i+$offset)])) break;
			
				$this->_arrMessages[] = array(
					'vdate'=>(string) $arrMessages[($i+$offset)]->vdate
					,'msgpost'=>(string) $arrMessages[($i+$offset)]->msgpost
				);
			}
		}
		
		// return number of total found rows
		return count($arrMessages);
	
	}
	
	public function getMessages() {
		return $this->_arrMessages;
	}

}

// set ordering
$order = isset($_GET['order']) && in_array($_GET['order'],array('asc','desc'))?$_GET['order']:'asc';

$action = new Action(strcmp($order,'asc') == 0?true:false);

$func = create_function('$offset,$limit,$action','return $action->paginate($offset,$limit);');
$pg = new Pagination($func,array(
	'basePath'=>$_SERVER['PHP_SELF'].'?p={replace_me_with_page}&order='.$order
	,'pageFlag'=>'{replace_me_with_page}'
	,'label'=>'Messages'
	,'limit'=>5
	,'page'=>isset($_GET['p']) && is_numeric($_GET['p']) && $_GET['p'] != 0?$_GET['p']:1
	,'visiblePages'=>5
	,'display_pages'=>0
	,'display_entity'=>0
),array($action));
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8">
	<title>Untitled</title>
	<style type="text/css">
	.pagination {
		text-align: center;
	}
	.pagination li {
		display: inline-block;
	}
	*+html .pagination li {
		display: inline;
	}
	* html .pagination li {
		display: inline;
	}
	</style>
</head>
<body>
	
	<?php
	printf(
		'<a href="%s?p=%u&order=%s">%s</a>'
		,$_SERVER['PHP_SELF']
		,$pg->getPage()
		,strcmp($order,'desc') == 0?'asc':'desc'
		,strcmp($order,'desc') == 0?'Ascending':'Descending'
	);
	?>

	<?php $paging = $pg->paginate(); ?>
	<?php echo $paging; ?>
	
	<?php 
	if($action->getMessages()) {
		echo '<ol>';
		foreach($action->getMessages() as $arrMessage) {
			printf(
				'<li>
					<p>%s</p>
					<p>%s</p>
				 </li>'
				 ,date('Y-m-d, H:i:s',$arrMessage['vdate'])
			 	,$arrMessage['msgpost']
			);
		} 
		echo '</ol>';
	} else {
		echo "<p>No messages available</p>";
	}?>
	
	<?php echo $paging; ?>
</body>
</html>

Sorry about all the stupid questions…as you can tell I really don’t have a good grasp of this.

Because my data is in a xml I change:


$strXML =
'<sayings>  <message>    <vdate>2010-06-01 00:48:21</vdate>    <msgpost>xxxxx</msgpost>  </message>
<message>
  <vdate>2010-06-09 00:48:21</vdate>
  <msgpost>xxxxx</msgpost>
</message>
<message>
  <vdate>2010-02-09 00:48:21</vdate>
  <msgpost>xxxxx</msgpost>
</message>
<message>
  <vdate>2010-02-09 00:48:21</vdate>
  <msgpost>xxxxx</msgpost>
</message>
<message>
  <vdate>2009-06-09 00:48:21</vdate>    <
  msgpost>xxxxx</msgpost>
</message>
</sayings>';

To:

$strXML = simplexml_load_file('xml/bev.xml');

I then get a bunch of errors " warning: simplexml_load_string() [function.somplexml-load-string]: Entity: line 2: parser error: Start tag expected, "<’ not found " which directs me to this line


* transform timestamps
*/
[B]$objXML = simplexml_load_string($strXML);[/B]
foreach($objXML->children() as $message)
 {
  $message->vdate = strtotime((string) $message->vdate);
 }

Could it be that my date is formated mm/dd/YYYY (in your sample it’s YYYY-mm-dd hh:mm:ss)

I can change that.

No, changing my date/time format to match yours did not help.

Look at the documentation for simplexml_load_string and you will see that the data needs to be “A well-formed XML string”

That means starting the string with a known XML doctype.


<?xml version='1.0'?>

See the example at http://www.php.net/manual/en/function.simplexml-load-string.php for an umm, example. :slight_smile:

I got a bit further.

I now get the fatal error “Call to a memver function children() on a non-object” and points to…

$strXML = simplexml_load_file('xml/bev.xml');

[B]$objXML = simplexml_load_string($strXML);[/B]
foreach(objXML->children() as $message){
}

I don’t see that it matters if I point to a string or a file when I assign $strXML?

I have no idea why your loading the XML twice. You only need to load XML file into a simple XML element once. The only reason a string was used in the code I wrote was so that everything was contained within a single script. Ideally though you would load the XML file into a simple XML object given its specific location within your application. Its just much easier to present sample code that takes that divide out of the equation.



$objXML = simplexml_load_file('xml/bev.xml');
foreach(objXML->children() as $message){
}

well I don’t get any error messages any more.
but then none of my xml content is showing up on the page either. All I see is “No messages available”.

oh, I will figure this out.
Thanks oddz

I get no error messages, however the code does not show any of my xml content. I know you wrote this for me and changed it for my needs…I feel really bad about asking you to help me even more. But please help.

It has got to be something very simple that I just can’t see.

xml

<sayings>
  <message>
    <vdate>2010-05-28 00:21:18</vdate>
    <msgpost>Hello World</msgpost>
  </message>
</sayings>
<?php
class Pagination {

    protected

    /*
    * Configuration defaults
    */
    $_arrConfig = array(
        'limit'=>10
        ,'page'=>1
        ,'basePath'=>'#'
        ,'label'=>'Items'
        ,'visiblePages'=>5
        ,'pageFlag'=>'{page}'
        ,'display_pages'=>1
        ,'display_entity'=>1
    )

    /*
    * Data to be passed to template
    */
    ,$_arrTemplateData = array()

    /*
    * function to pass resolved offset and limit
    */
    ,$_onPaginate

    /*
    * extra arguments to pass to to pagination callback
    * such as data source or db connection
    */
    ,$_arrArgs;

    public function __construct($onPaginate,$arrConfig=array(),$arrArgs=array()) {

        $this->_onPaginate = $onPaginate;
        $this->_arrArgs = $arrArgs;

        foreach($arrConfig as $strKey=>$mixValue) {
            if(array_key_exists($strKey,$this->_arrConfig)) {
                $this->_arrConfig[$strKey] = $mixValue;
            }
        }
    }

    public function paginate() {

        /*
        * Calculate page offset
        */
        $intOffset = ($this->_arrConfig['page']-1)*$this->_arrConfig['limit'];

        /*
        * Paginate and get number of found rows
        */
        $intFoundRows = call_user_func_array($this->_onPaginate,array_merge(array($intOffset,$this->_arrConfig['limit']),$this->_arrArgs));

        /*
        * Assign template data
        */
        $this->_arrTemplateData['limit'] = $this->_arrConfig['limit'];
        $this->_arrTemplateData['page'] = $this->_arrConfig['page'];
        $this->_arrTemplateData['offset'] = $intOffset;
        $this->_arrTemplateData['found_rows'] = $intFoundRows;
        $this->_arrTemplateData['total_pages'] = $intFoundRows < $this->_arrConfig['limit']?1:ceil($intFoundRows/$this->_arrConfig['limit']);
        $this->_arrTemplateData['visible_pages'] = $this->_arrConfig['visiblePages'];
        $this->_arrTemplateData['base_path'] = $this->_arrConfig['basePath'];
        $this->_arrTemplateData['label'] = $this->_arrConfig['label'];
        $this->_arrTemplateData['page_flag'] = $this->_arrConfig['pageFlag'];
        $this->_arrTemplateData['display_pages'] = $this->_arrConfig['display_pages'];
        $this->_arrTemplateData['display_entity'] = $this->_arrConfig['display_entity'];

        /*
        * Return the pagination template
        */
        return $this->display();
    }

    public function display() {
        extract($this->_arrTemplateData);

        if($total_pages <= $visible_pages) {
            $page_start = 1;
            $page_end = $total_pages;
        } else if($page <= ceil($visible_pages/2)) {
            $page_start = 1;
            $page_end = $visible_pages;
        } else if($page > ($total_pages - ceil($visible_pages/2))) {
            $page_start = $total_pages - (ceil(($visible_pages/2)*2)-1);
            $page_end = $total_pages;
        } else {
            $page_start = $page-(floor($visible_pages/2));
            $page_end = $page+(floor($visible_pages/2));
        }

        $return='';

        if($display_pages && $display_entity) {
        $return.= sprintf(
               '<div class="summary"><p class="pages">%u %s</p><p class="total">%u %s</p></div>'
            ,$total_pages
            ,$total_pages == 1?'Page':'Pages'
            ,$found_rows
            ,$found_rows == 1?$label:$label
        );
        }

        $return.= sprintf('<ul class="pagination">');
        $return.= sprintf(
            '<li class="first">%s%s%s</li>'
            ,$page == 1?'':sprintf('<a href="%s">',str_replace($page_flag,1,$base_path))
            ,'First'
            ,$page == 1?'':'</a>'
        );
        $return.= sprintf(
            '<li class="previous">%s%s%s</li>'
                ,$page == 1?'':sprintf('<a href="%s">',str_replace($page_flag,($page-1),$base_path))
            ,'Previous'
            ,$page == 1?'':'</a>'
        );
        foreach(range($page_start,$page_end,1) as $i) {
            $return.= sprintf(
                '<li%s>%s%s%s</li>'
                ,$page == $i?' class="current"':''
                ,$page == $i?'':sprintf('<a href="%s">',str_replace($page_flag,$i,$base_path))
                ,$i
                ,$page == $i?'':'</a>'
            );
        }
        $return.= sprintf(
            '<li class="next">%s%s%s</li>'
            ,$page == $total_pages?'':sprintf('<a href="%s">',str_replace($page_flag,($page+1),$base_path))
            ,'Next'
            ,$page == $total_pages?'':'</a>'
        );
        $return.= sprintf(
            '<li class="last">%s%s%s</li>'
            ,$page == $total_pages?'':sprintf('<a href="%s">',str_replace($page_flag,$total_pages,$base_path))
            ,'Last'
            ,$page == $total_pages?'':'</a>'
        );
        $return.= sprintf('</ul>');

        return $return;

    }
    /*
    * Get current page
    */
    public function getPage() {
        return $this->_arrConfig['page'];
    }

}

class Action {

    private $_objXML;
    private $_boolAscending = true;
    private $_arrMessages = array();

    public function __construct($boolAscending=true) {

        /*
        * Set ordering
        */
        $this->_boolAscending = $boolAscending;

        $objXML = simplexml_load_file('xml/bev.xml');

        /*
        * transform timestamps
        */
        foreach($objXML->children() as $message) {
            $message->vdate = strtotime((string) $message->vdate);
        }


        $strStyle =
'<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions">

    <xsl:template match="/">
        <xsl:call-template name="content">
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="content">
        <sayings>
        <xsl:for-each select="/sayings/message">
            <xsl:sort select="vdate" data-type="number" order="'.($this->_boolAscending?'ascending':'descending').'"/>
            <message>
                <vdate><xsl:value-of select="vdate"/></vdate>
                <msgpost><xsl:value-of select="msgpost"/></msgpost>
            </message>
        </xsl:for-each>
        </sayings>
    </xsl:template>

</xsl:stylesheet>';


        /*
        * Load message DOM document
        */
        $objMessage = new DOMDocument();
        $objMessage->loadXML($objXML->asXML());

        /*
        * Load transform DOM document
        */
        $objStylesheet = new DOMDocument();
        $objStylesheet->loadXML($strStyle);

        /*
        * Create XSLT processor ansd set stylesheet
        */
        $objXSLT = new XSLTProcessor();
        $objXSLT->importStylesheet($objStylesheet);

        /*
        * apply transform
        */
        $this->_objXML = simplexml_load_string($objXSLT->transformToXML($objMessage));


    }

    public function paginate($offset,$limit) {

        $arrMessages = $this->_objXML->xpath('message');

        if(isset($arrMessages[$offset])) {
            for($i=0;$i<$limit;$i++) {

                if(!isset($arrMessages[($i+$offset)])) break;

                $this->_arrMessages[] = array(
                    'vdate'=>(string) $arrMessages[($i+$offset)]->vdate
                    ,'msgpost'=>(string) $arrMessages[($i+$offset)]->msgpost
                );
            }
        }

        // return number of total found rows
        return count($arrMessages);

    }

    public function getMessages() {
        return $this->_arrMessages;
    }

}

// set ordering
$order = isset($_GET['order']) && in_array($_GET['order'],array('asc','desc'))?$_GET['order']:'asc';

$action = new Action(strcmp($order,'asc') == 0?true:false);

$func = create_function('$offset,$limit,$action','return $action->paginate($offset,$limit);');
$pg = new Pagination($func,array(
    'basePath'=>$_SERVER['PHP_SELF'].'?p={replace_me_with_page}&order='.$order
    ,'pageFlag'=>'{replace_me_with_page}'
    ,'label'=>'Messages'
    ,'limit'=>5
    ,'page'=>isset($_GET['p']) && is_numeric($_GET['p']) && $_GET['p'] != 0?$_GET['p']:1
    ,'visiblePages'=>5
    ,'display_pages'=>0
    ,'display_entity'=>0
),array($action));
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>Untitled</title>
    <style type="text/css">
    .pagination {
        text-align: center;
    }
    .pagination li {
        display: inline-block;
    }
    *+html .pagination li {
        display: inline;
    }
    * html .pagination li {
        display: inline;
    }
    </style>
</head>
<body>

    <?php
    printf(
        '<a href="%s?p=%u&order=%s">%s</a>'
        ,$_SERVER['PHP_SELF']
        ,$pg->getPage()
        ,strcmp($order,'desc') == 0?'asc':'desc'
        ,strcmp($order,'desc') == 0?'Ascending':'Descending'
    );
    ?>

    <?php $paging = $pg->paginate(); ?>
    <?php echo $paging; ?>

    <?php
    if($action->getMessages()) {
        echo '<ol>';
        foreach($action->getMessages() as $arrMessage) {
            printf(
                '<li>
                    <p>%s</p>
                    <p>%s</p>
                 </li>'
                 ,date('Y-m-d, H:i:s',$arrMessage['vdate'])
                 ,$arrMessage['msgpost']
            );
        }
        echo '</ol>';
    } else {
        echo "<p>No messages available</p>";
    }?>

    <?php echo $paging; ?>

btw: how do cut and paste your code keeping the colors? I have the colors in my code when it’s in dreamweaver but when I copy and paste it looses the colors.

At this point I’m not exactly sure why it isn’t working for you. I just copy and pasted the script to a new file. Created a folder in the same directory called xml and copy and pasted the xml into a file called bev.xml. Everything worked fine for me. Perhaps your XML file path is incorrect?

One way to debug that issue is to see if the XML file is even being loaded.


$objXML = simplexml_load_file('xml/bev.xml');

// right here dump the XML to confirm its existence
echo '<pre>',print_r($objXML),'</pre>';

foreach(objXML->children() as $message){
} 

The other thing it may be is your version of PHP or XSLTProcessor is enabled?

run this simple script outside of the other one:


echo class_exists('XSLTProcessor')?'Y':'N';

Is the answer Y or N?

Your XML should look like this:


<?xml version="1.0"?>
<sayings>
  <message>
    <vdate>2010-05-28 00:21:18</vdate>
    <msgpost>Hello World</msgpost>
  </message>
  <message>
    <vdate>2010-05-28 00:21:18</vdate>
    <msgpost>Hello World</msgpost>
  </message>
  <message>
    <vdate>2010-05-28 00:21:18</vdate>
    <msgpost>Hello World</msgpost>
  </message>
</sayings>

All those issues would likely result in errors but you may have some type of suppression or something going on.