2012-05-11 2 views
1

Вот моя проблема, мне нужно обновить файл XML с помощью другого XMLPerl XML :: Twig Обновление файл XML с другим XML

data.xml:

<?xml version='1.0'?> 
<employees> 
<employee> 
    <employeenumber>V0000001</employeenumber> 
    <name>John Doe</name> 
    <age>43</age> 
    <sex>M</sex> 
    <department>Operations</department> 
</employee> 
<employee> 
    <employeenumber>V0000002</employeenumber> 
    <name>Jane Doe</name> 
    <age>35</age> 
    <sex>F</sex> 
    <department>Operations</department> 
</employee> 
<employee> 
    <employeenumber>V0000003</employeenumber> 
    <name>Jane Doe</name> 
    <age>35</age> 
    <sex>F</sex> 
    <department>Operations</department> 
</employee> 
<employee> 
    <employeenumber>V0000004</employeenumber> 
    <name>Jane Doe</name> 
    <age>35</age> 
    <sex>F</sex> 
    <department>Operations</department> 
</employee> 
<employee> 
    <employeenumber>V0000005</employeenumber> 
    <name>Jane Doe</name> 
    <age>35</age> 
    <sex>F</sex> 
    <department>Operations</department> 
</employee> 
</employees> 

data2.xml:

<?xml version='1.0'?> 
<employees> 
<employee> 
    <employeenumber>V0000002</employeenumber> 
    <name>Jane Doe</name> 
    <age>34</age> 
    <sex>F</sex> 
    <department>Management</department> 
</employee> 
<employee> 
    <employeenumber>V0000004</employeenumber> 
    <name>Jane Doe</name> 
    <age>34</age> 
    <sex>F</sex> 
    <department>Sales</department> 
</employee> 
</employees> 

Так что мне нужно обновить Data.xml с информацией из Data2.xml.

Я написал этот код, он работает, но требуется 6 часов для выполнения, Data.xml довольно большой (250mo).

use XML::Twig; 
my %soi =(); 
open(FILE,">out.txt"); 


my $diff= XML::Twig->new(pretty_print => 'indented', 
         twig_handlers => 
         { 'employees/employee' => \&stock_n_purge,} 
        ) 
       ->parsefile('data2.xml'); 


sub stock_n_purge 
{ 
my($diff, $elt)= @_; 
$soi{$elt->first_child ("employeenumber")->text} = "1"; # stock l'element dans un tableau 
$diff->print(\*FILE); 
printf "Found One"; 
$diff->purge;# frees the memory 
} 


my $full= XML::Twig->new(pretty_print => 'indented', 
         twig_handlers => 
         { 'employees/employee' => \&stock_n_purge2,} 
        ) 
       ->parsefile('data.xml'); 


sub stock_n_purge2 
{ 
my($diff2, $elt2)= @_; 
$diff2->print(\*FILE) unless (exists($soi{$elt2->first_child ("employeenumber")->text})); 
$diff2->purge; # frees the memory 
} 

close(FILE); 

EmployeeNumber быть уникальным, я пишу каждый элемент data2.xml в новый файл, и я хранить каждый employeenumbers в массиве. Затем я разбираю data.xml и записываю каждый элемент, если он не существует в массиве.

Этот метод неэффективен вообще. Поэтому вместо того, чтобы переписывать все data.xml, я хотел бы удалить каждый элемент из data.xml, который существует в массиве (и, следовательно, в data2.xml). Затем добавьте элементы из data2.xml в data.xml

Моя проблема в том, что я не могу найти способ удалить элемент из XML-файла с помощью XML Twig.

Есть ли у кого-нибудь идеи?

Заранее благодарен,

Simon.

+0

У Twig есть метод 'delete' для удаления элементов. – toolic

ответ

2

С быстрым просмотром кода, мне кажется, что вы печатаете оба файла много, много, много раз. Действительно, вы печатаете весь файл для каждого найденного вами элемента, когда вы делаете $diff->print. Я действительно не отлаживал ваш код, но я подозреваю, что вы хотите использовать flush вместо print. Попробуйте и сообщите нам, если что-то улучшится.

+0

Хорошо, я не понял, что могу писать в файл с флешем. Благодарю. Теперь код исполняется 20 минут, вместо 6 часов. Совершенное улучшение ^^. Большое спасибо. – user1361295

+0

'print' печатает все дерево, а' flush' печатает то, что было обработано до сих пор, отслеживая элементы, которые еще не закрыты, а затем освобождает память, поэтому все дерево не нужно хранить в памяти – mirod