我使用 XML::Twig 處理程式/根從大型 XML 檔案中提取資訊,其中將整個檔案加載到記憶體中的成本太高。這些 XML 檔案是 Excel .xlsx 檔案的內部作業表檔案。
到目前為止,這種方法一直運作良好。下面是從內部 XML 檔案 sheet1.xml 中提取所有單元格參考的示例。
use strict;
use warnings;
use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
use XML::Twig;
use Data::Dumper;
my $zipName='TestFile.xlsx';
my $zip = Archive::Zip->new();
my $zipread;
$zipread=$zip->read($zipName);
my $tw1=new XML::Twig();
my $fileToAnalyse='xl/worksheets/sheet1.xml';
my $sheetFile = $zip->contents($fileToAnalyse);
my @Results;
my $t= XML::Twig->new(twig_roots => {'worksheet/sheetData/row/c' =>
sub { Get_Sheet_Data_TEST_1(@_,\@Results);}})->parse($sheetFile);
print Dumper \@Results;
sub Get_Sheet_Data_TEST_1{
my($t,$elt,$Results)= @_;
my @attrib_NAMES=$elt->att_names();
for my $attrib_loop (0 .. scalar @attrib_NAMES-1){
if($attrib_NAMES[$attrib_loop] eq 'r'){
push @$Results,$elt->att($attrib_NAMES[$attrib_loop]);
}
}
$t->purge; # frees the memory
}
有時這些檔案有我正在尋找的標簽的前綴
所以
'worksheet/sheetData/row/c'
變成
'x:worksheet/x:sheetData/x:row/x:c'
現在我的處理程式永遠不會觸發,因為它沒有找到所需的標簽。
有沒有什么辦法可以修改我的處理程式,而不用硬編碼所有可能的前綴可能性,所以這些前綴可以與沒有前綴的“通常”標簽一樣匹配?
也許有一種方法可以提前找到任何給定檔案使用的前綴,并將這些值設定為一個變數,然后我可以將其傳遞給我的處理程式。
uj5u.com熱心網友回復:
好的,我找到了解決方案。原來 XML::Twig 有一個可選引數
map_xmlns
我可以用它來解決我的問題。所以,我的原始代碼
my $t= XML::Twig->new(twig_roots => {'worksheet/sheetData/row/c' =>
sub { Get_Sheet_Data_TEST_1(@_,\@Results);}})->parse($sheetFile);
變成
my $t= XML::Twig->new(
map_xmlns => {
'http://schemas.openxmlformats.org/spreadsheetml/2006/main' => 's'},
twig_roots => {'s:worksheet/s:sheetData/s:row/s:c' =>
sub { Get_Sheet_Data_TEST_1(@_,\@Results);}})->parse($sheetFile);
現在我的處理程式適用于所有前綴(甚至是空的!)。
正如 XML::Twig 檔案中所寫:
map_xmlns
這個選項被傳遞了一個將uri映射到前綴的hashref。檔案中的前綴將替換為地圖中的前綴。映射的前綴可以(實際上必須)用于觸發處理程式、導航或查詢檔案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/417702.html
標籤:
