使用XMLReader获取XML代码计数


Get XML code count using XMLReader

我正在尝试解析提供给谷歌商家的产品提要。问题是我希望它更具交互性,所以我使用了一个函数,将XML转换为数组,然后向用户显示产品更新量的百分比。我读到XMLReader比其他解析技术效率高得多
如何使XMLReader更有效。我可以使用XMLReader获取节点数吗。或者,我如何对XML进行迭代,使其能够更具响应性。

将XML转换为数组是错误的想法。这将意味着您在内存中构建数据结构。但是您已经有了一个数据结构,因此将其转换为数组将意味着您丢失数据和功能。始终直接读取XML并使用它。

以下是几种存档所需内容的方法。如果提要很小,您可以直接使用DOM。这允许您使用XPaths的count()函数。

谷歌产品提要基于RSS 2.0或Atom 1.0。Atom是更好的格式,所以让我们使用它。

// create a DOM document and load the XML 
$dom = new DOMDocument();
$dom->loadXml($xml);
// Create a xpath object and register prefixes for the two namespaces
$xpath = new DOMXpath($dom);
$xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom');
$xpath->registerNamespace('gi', 'http://base.google.com/ns/1.0');
// Output the entry count
var_dump($xpath->evaluate('count(//atom:entry)'));
// iterate the entries
foreach ($xpath->evaluate('//atom:entry') as $entry) {
  // output some data from them
  var_dump(
    [
      'title' => $xpath->evaluate('string(atom:title)', $entry),
      'summary' => $xpath->evaluate('string(atom:summary)', $entry),
      'image-link' => $xpath->evaluate('string(gi:image_link)', $entry)
    ]
  );
}

如果产品提要非常大,那么将其完全加载到内存中可能不起作用。但要获得计数,您必须将它们加载到内存中或迭代两次。一种可能的方法是文件大小。当然,这不会是确切的进展。但应该足够好。

$file = 'feed.xml';
$fileSize = filesize('feed.xml');
$readBytes = 0;
// get an xml reader for the file
$reader = new XMLReader;
$reader->open($file);
// get an xml document, xpath and register the namespaces
$dom = new DOMDocument();
$xpath = new DOMXpath($dom);
$xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom');
$xpath->registerNamespace('gi', 'http://base.google.com/ns/1.0');
// look for the first entry element
while ($reader->read() && $reader->localName !== 'entry') {
  continue;
}
// while you have an entry element
while ($reader->localName === 'entry') {
  // import the entry into the prepared document
  $entry = $reader->expand($dom);
  var_dump(
    [
      'title' => $xpath->evaluate('string(atom:title)', $entry),
      'summary' => $xpath->evaluate('string(atom:summary)', $entry),
      'image-link' => $xpath->evaluate('string(gi:image_link)', $entry)
    ]
  );
  $readBytes += strlen($reader->readOuterXml());
  printf(
    'Read %s of %s bytes, %d%%',
    $readBytes,
    $fileSize,
    round($readBytes * 100 / $fileSize)
  );
  // move to the next entry sibling
  $reader->next('entry');
}

请注意,使用XML阅读器会比较慢。计算状态也会带来性价比。仅仅显示已经阅读了多少条目可能是一个更好的主意。

使用DOM,您可以计算任何节点。

$dom = new DOMDocument;
$dom->loadXml($xml);
echo $dom->getElementsByTagName('OfferName')->length;