2016-11-10 31 views
2

一個XML文件,下面給出的XML特定名稱的所有元素:計數使用PHP

<Items> 
    <Item>...</Item> 
    <Item>...</Item> 
    <Item>...</Item> 
    <Item>...</Item> 
</Items> 

我寫一個函數(在這種情況下,4)返回所有<Item>元素的數量。實際的XML文件非常龐大,我不想將整個內容加載到內存中來解析它。

使用命令行,我設法得到什麼,我需要用下面一行:

grep "<Item>" my_file.xml -o | wc -l 

是否有PHP的等效的解決方案,我可以用它來得到相同的結果?

回答

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); 
+0

我最終使用'DOMDocument'爲現在。但SAX解析器對於大文件來說絕對是更好的選擇,因爲它是基於事件的解析器而不是基於樹的。 –