Po napotkaniu plików danych XML zawierających olbrzymie węzły tekstowe, szukałem sposobów na odczytanie i ocenę ich w moich skryptach przetwarzania danych. .Praktyczny sposób odczytywania xml z dużymi węzłami tekstowymi w Perl
plików XML są 3D koordynować pliki do modelowania molekularnego aplikacje mają taką strukturę (przykład):
<?xml version="1.0" encoding="UTF-8"?>
<hoomd_xml version="1.4">
<configuration>
<position>
-0.101000 0.011000 -40.000000
-0.077000 0.008000 -40.469000
-0.008000 0.001000 -40.934000
-0.301000 0.033000 -41.157000
0.213000 -0.023000 -41.348000
...
... 300,000 to 500,000 lines may follow >>
...
-0.140000 0.015000 -42.556000
</position>
<next_huge_section_of_the_same_pattern>
...
...
...
</next_huge_section_of_the_same_pattern>
</configuration>
</hoomd_xml>
poszczególnych plików XML zawiera kilka węzłów ogromny tekstowych i ma rozmiary między 60 MB i 100 MB w zależności od zawartości.
Próbowałem naiwny approch użyciu XML::Simple pierwszy ale ładowarka zajęłoby wieki wstępnie przeanalizować plik:
...
my $data = $xml->XMLin('structure_80mb.xml');
...
i powstrzymać się od „Błąd wewnętrzny: wejściowego ogromnego odnośnika”, więc to podejście ISN” t bardzo praktyczne.
Kolejna próba była w użyciu XML::LibXML do czytania - ale tutaj, początkowa ładowarka będzie wyskoczyć natychmiast z komunikatem o błędzie „parser error: xmlSAX2Characters: ogromny węzeł tekst”.
Befor pisanie na ten temat na stackoverflow pisałem aq & d parsera dla siebie i wysłał plik przez niego (po slurping xx MB plik xml do skalara $xml
):
...
# read the <position> data from in-memory xml file
my @Coord = xml_parser_hack('position', $xml);
...
który zwraca dane z każdej linii jako tablicę, kończy w ciągu kilku sekund i wygląda następująco:
sub xml_parser_hack {
my ($tagname, $xml) = @_;
return() unless $xml =~ /^</;
my @Data =();
my ($p0, $p1) = (undef,undef);
$p0 = $+[0] if $xml =~ /^<$tagname[^>]*>[^\r\n]*[r\n]+/msg; # start tag
$p1 = $-[0] if $xml =~ /^<\/$tagname[^>]*>/msg; # end tag
return() unless defined $p0 && defined $p1;
my @Lines = split /[\r\n]+/, substr $xml, $p0, $p1-$p0;
for my $line (@Lines) {
push @Data, [ split /\s+/, $line ];
}
return @Data;
}
działa to dobrze, ale do tej pory nie można uznać za „produkcję gotowy”, oczywiście.
P: Jak odczytałbym plik za pomocą modułu Perla? Który moduł wybiorę?
góry dzięki
RBO
Uzupełnienie: po przeczytaniu komentarza choroba jest, spojrzałem w głąb XML :: libxml. Otwarcie pliku my $reader = XML::LibXML::Reader->new(location =>'structure_80mb.xml');
działa, w przeciwieństwie do tego, co wcześniej sądziłem. Błąd występuje, gdy próbuję uzyskać dostęp do węzła tekstowego poniżej tagu:
...
while ($reader->read) {
# bails out in the loop iteration after accessing the <position> tag,
# if the position's text node is accessed
# -- xmlSAX2Characters: huge text node ---
...
http://search.cpan.org/~mirod/XML-Twig -3.44/Twig.pm - moduł perla do przetwarzania ogromnych dokumentów XML w trybie drzewa. –
Jak otworzyłeś plik z XML :: LibXML? Działa dla mnie dla plików o wielkości 100 MB. – choroba
@choroba - dzięki, sprawdziłem ponownie - i zaktualizowałem temat. –