1

我有一个非常大的 RSS xml 文件,有 700 多个节点。我正在使用XMLReader Iterator 库对其进行解析并将结果显示为每页 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 文件时应用限制吗?

我遇到了Gordon的这个回答,它解决了一个类似的问题,但它使用的是 SimpleXML,不推荐用于解析大型 xml 文件。

4

4 回答 4

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);
于 2013-09-14T10:03:54.370 回答
1

在这种情况下使用缓存,因为您不能部分解析 XML。

于 2013-09-04T15:07:34.320 回答
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 ++;
}
于 2013-09-09T11:34:51.253 回答
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

于 2013-09-06T05:00:52.857 回答