鉴于以下XML:
<Items>
<Item>...</Item>
<Item>...</Item>
<Item>...</Item>
<Item>...</Item>
</Items>
我正在编写一个函数来返回所有<Item>
元素的计数(在本例中为4)。实际的XML文件很大,我不想在内存中加载整个东西以便解析它。
使用命令行,我设法通过以下行获得了我需要的东西:
grep "<Item>" my_file.xml -o | wc -l
我是否可以使用PHP中的等效解决方案来获得相同的结果?
答案 0 :(得分:1)
使用XPath很容易完成:
$doc = new DOMDocument();
$doc->load('my_file.xml', LIBXML_PARSEHUGE);
$xp = new DOMXPath($doc);
$count = $xp->evaluate('count(//Item)');
XPath表达式返回文档中所有 Item
标记的数量。
LIBXML_PARSEHUGE
选项仅影响深度,实体递归和文本节点大小的内部限制。但是,DOM解析器将整个文档加载到内存。
对于非常大的文件,使用SAX parser,它按顺序对每段XML进行操作(因此只将文档的一小部分加载到内存中):
$counter = 0;
$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, function ($parser, $name) use (&$counter) {
if ($name === 'ITEM') {
$counter++;
}
}, null);
if (!($fp = fopen('my_file.xml', 'r'))) {
die('Could not open XML input');
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
xml_parser_free($xml_parser);