2013-02-26 1 views
2

У меня есть гигантский XML-файл (около 10 Гб), который мне нужно преобразовать в CSV. Теперь этот файл будет содержать информацию о многочисленных клиентах. Мне нужно преобразовать его в формат CSV. Проблема заключается в том, что у многих клиентов будут дополнительные поля, которые другие клиенты привыкли, и некоторые из полей будут повторяться. Пример XML является:Perl XML :: Twig. Гигантская обработка файлов. Как обрабатывать повторяющиеся enteries & enteries, которых нет

<customer> 
<customerID>1</customerID> 
    <auc> 
     <algoId>0</algoId> 
     <kdbId>1</kdbId> 
     <acsub>1</acsub> 
    </auc> 
</customer> 

<customer> 
<customerID>2</customerID> 
    <auc> 
     <algoId>0</algoId> 
     <kdbId>1</kdbId> 
     <acsub>1</acsub> 
     <extraBit>12345</extraBit> 
    </auc> 
    <auc> 
     <algoId>2</algoId> 
     <kdbId>3</kdbId> 
     <acsub>3</acsub> 
     <extraBit>67890</extraBit> 
    </auc> 
     <customOptions> 
      <odboc>0</odboc> 
    <odbic>0</odbic> 
    <odbr>1</odbr> 
    <odboprc>0</odboprc> 
    <odbssm>0</odbssm> 
</customOptions> 
</customer> 

Теперь, как вы можете видеть, первый клиент имеет только 1 АУК блок, но второй из них имеет 2, кроме того, он также имеет дополнительный тег в ППК, который extraBit. Теперь вопросы:

  1. я должен обрабатывать один клиент одновременно (от одного клиента к/клиента, а затем так далее), а 10 Гб atonce приведет к краху системы.

  2. Я пытаюсь использовать XML прутик в цикле, и когда я пытаюсь extraBit для Клиента 1, завершает программу «неопределенного значения»:

    печати $ на клиент> first_child («extraBit») - > текст()

    Невозможно вызвать метод «текст» на неопределенное значение в xml-tags.pl линии 50.

  3. для дополнительных АУК для клиента Я хочу, чтобы выводиться в формате CSV файл как:

    клиентID, algoId, kdbId , Acsub, extraBit, algoId2, kdbId2, acsub2, extraBit2

    1,0,1,1 ,,,,,,

    2,0,1,1,1234,2,3,3,67890

+0

я как-то сложилось ощущение, что вы должны скорее выполнить это с процессором XSLT. Взгляните на http://xmlsoft.org/XSLT/xsltproc2.html и немного почитайте о XSLT. Базовая обработка на самом деле довольно проста. http://stackoverflow.com/questions/7294344/convert-xml-to-csv-using-xslt – simbabque

+0

И, пожалуйста, покажите еще несколько своих кодов Perl. Трудно понять, что у вас уже есть. – simbabque

+0

@simbabque наоборот, использование XSLT потребует разбора всего 10 ГБ файла в память за один раз. Использование 'XML :: Twig' и, в частности, механизма' twig_handlers', означает, что вы можете проходить через клиентов по очереди потоковым способом. –

ответ

3
print $customer->first_child('extraBit')->text() 

вы можете избежать неопределенной ошибки при использовании first_child_text вместо этого, который определяется возвращать пустую строку, если нет дочернего элемента соответствия не может быть найден.

print $customer->first_child_text('extraBit') 

Полный код будет нечто вроде

my $t= XML::Twig->new(
    twig_handlers => { customer => \&process_customer }); 
$t->parsefile('file.xml'); 

sub process_customer { 
    my ($t, $customer) = @_; 
    print $customer->first_child_text('customerID'); 
    foreach my $auc ($customer->children('auc')) { 
    print ',', $auc->first_child_text('algoId'), 
      ',', $auc->first_child_text('kdbId'), 
      ',', $auc->first_child_text('acsub'), 
      ',', $auc->first_child_text('extraBit'); 
    } 
    print "\n" 
    $customer->purge; 
} 
+0

Спасибо @ Ian Roberts, это очень помогло. Сегодня я начал использовать веточку, так что немного озадачен. Ваш код работал отлично, но если у меня есть более одного блока клиента, он терпит неудачу с 'junk after document element в строке 10, столбец 0, байт 158 в \ lib \ XML \ Parser.pm line 187'. Во-вторых, я немного редактировал содержимое файла XML (извините, немного поздно), посмотрите на xml выше). – Muzammil

+0

@Muzammil XML все еще должен быть хорошо сформирован, что, в частности, означает, что ему нужен элемент _single_ root - если ваш файл представляет собой последовательность элементов «» один за другим без единого корневого элемента, тогда вам придется оберните корневой элемент вокруг всего файла (например, добавьте '' вверху и '' внизу. –

+0

@Muzammil и вам может понадобиться защитить некоторые ваши вызовы 'children' с помощью соответствующего' if ($ customer-> has_children ('...')) ', чтобы освещать случаи, когда они могут отсутствовать. –

 Смежные вопросы

  • Нет связанных вопросов^_^