【问题标题】:how to read only part of an xml file with php xmlreader如何使用 php xmlreader 仅读取 xml 文件的一部分
【发布时间】:2013-09-08 03:30:26
【问题描述】:

我有一个非常大的 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 文件时应用限制吗?

我遇到了 Gordonthis answer,它解决了类似的问题,但它使用的是 SimpleXML,不建议将其用于解析大型 xml 文件。

【问题讨论】:

标签: php xml xml-parsing xmlreader


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    检查一下

    <?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

    【讨论】:

    • 这适用于包含大约 200 个节点的 xml 文件。但是,如果我使用大型 xml 文件尝试此代码(根据要求),我会收到内部服务器错误。
    【解决方案3】:

    您可以使用 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 ++;
    }
    

    【讨论】:

    • 我试过这段代码。对于大型 xml 文件(700 项),即使这样也会产生内部服务器错误。最后一个 print_r 语句之后应该有一个 break; 。否则项目会被打印多次。
    • 您遇到了什么样的内部服务器错误?你有错误代码吗?
    • print_r 只是为了向您展示各种节点可以做什么。结果取决于实际的内容提要。
    • 这里对我有用。如果您收到错误,您应该检查您的 Web 服务器的错误日志。您的脚本要么抛出内存不足错误,因为文件太大,要么抛出最大执行时间错误,因为下载提要需要很长时间。我已经编辑了代码,以便在将提要加载到 XML 解析器后,它通过重置 $string 变量来释放内存。我还修复了 print_r,现在可以正常工作了。
    • 如果您需要在远程服务器上解析较长的 RSS 提要,建议将其缓存在本地,这样您就不必每次需要输出新页面时都获取它。
    【解决方案4】:

    使用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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-05
      • 2017-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-17
      • 2017-04-13
      • 2013-09-08
      相关资源
      最近更新 更多