如何使用php xmlreader只读取部分xml文件

时间:2013-09-04 14:46:45

标签: php xml xml-parsing xmlreader

我有一个非常大的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文件。

4 个答案:

答案 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 ++;
}