我正在尝试解析提供给谷歌商家的产品提要。问题是我希望它更具交互性,所以我使用了一个函数,将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;