我有一个非常大的RSS xml文件,有超过700个节点。 我使用XMLReader Iterator library来解析它并将结果显示为每页10个。
这是我解析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 '<a href="'.$items[$i]['link'].'">'.$items[$i]['title'].'</a><br>';
}
?>
但问题是,对于每个页面,我正在解析整个xml文件,然后只显示相应的页面结果,如:如果页面为1,则显示1到10个节点,如果页面为5 ,显示41到50个节点。
导致显示数据延迟。是否可以只读取与所请求页面相对应的节点?因此,对于第一页,我可以读取1到10个位置的节点,而不是解析所有xml文件,然后显示前10个节点。换句话说,我可以在解析xml文件时应用限制吗?
我遇到了{strong> Gordon 的this answer,它解决了类似的问题,但它使用的是SimpleXML,不推荐用于解析大型xml文件。
答案 0 :(得分:2)
使用array_splice
提取数组的部分
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 '<a href="' . $arrayItem[$i]['link'] . '">' . $arrayItem[$i]['title'] . '</a><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('<a href="?page=%d" style="color:green">%d</a>', $i, $i);
}
}
echo implode('', $str);
答案 1 :(得分:1)
在这种情况下使用缓存,因为您无法部分解析XML。
答案 2 :(得分:1)
检查
<?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 "<a href=\"$value->link\">$value->title</a>";
echo "<br>";
}
}
//and the pagination:
//echo $currentRecord;
for ($i = 1; $i <= ($currentRecord / $perPage); $i++) {
echo("<a href='xmlpagination.php?page=".$i."'>".$i."</a>");
} ?>
的更新强> 的
检查此链接
http://www.phpclasses.org/package/5667-PHP-Parse-XML-documents-and-return-arrays-of-elements.html
答案 3 :(得分:1)
您可以使用Dom和Xpath。它应该快得多,因为Xpath允许您按列表中的位置选择节点。
<?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 ++;
}