1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<Produkt>
<Produkt_Nummer>5</Produkt_Nummer>
<details>
<details2>..</2details>
</details>
</Produkt>
<Produkt>
<Produkt_Nummer>5</Produkt_Nummer>
<details>
<details2>..</2details>
</details>
</Produkt>
<Produkt>
<Produkt_Nummer>5</Produkt_Nummer>
<details>
<details2>..</2details>
</details>
</Produkt>
<Produkt>
<Produkt_Nummer>5</Produkt_Nummer>
<details>
<details2>..</2details>
</details>
</Produkt>
<Produkt>
<Produkt_Nummer>9</Produkt_Nummer>
<details>
<details2>..</2details>
</details>
</Produkt>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
#!/usr/bin/perl use strict; use warnings; use XML::Twig; my $file = 'test.xml'; my %seen; my $twig = XML::Twig->new( # twig_roots macht aus jedem <Produkt>-Block # ein eigenständiges "Objekt" # Für jeden Block wird die Methode "produkt" aufgerufen twig_roots => { Produkt => \&produkt, }, # gib einfach alles außerhalb der Produkt-Blöcke # aus. twig_print_outside_roots => 1, )->parsefile( $file ); sub produkt { my ($t,$elt) = @_; # hole die ProduktNummer my ($nr) = $elt->children( 'Produkt_Nummer' ); my $id = $nr->text; if ( $seen{$id}++ ) { # wenn es einen Block für die ProduktNummer bereits # gibt, dann lösche den aktuellen Block... $elt->delete; } else { # ansonsten gib ihn aus $elt->print; } # gib den Speicher frei $t->purge; }
2013-07-16T08:41:12 FanClubWie hast Du es denn probiert?Leider läuft dein mechanismus auch auf einen Out of Memory.
2013-07-16T08:41:12 FanClubIch habe eine XML Datei. So aufgebaut (grob)
Code: (dl )1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30<Produkt>
<Produkt_Nummer>5</Produkt_Nummer>
<details>
<details2>..</2details>
</details>
</Produkt>
<Produkt>
<Produkt_Nummer>5</Produkt_Nummer>
<details>
<details2>..</2details>
</details>
</Produkt>
<Produkt>
<Produkt_Nummer>5</Produkt_Nummer>
<details>
<details2>..</2details>
</details>
</Produkt>
<Produkt>
<Produkt_Nummer>5</Produkt_Nummer>
<details>
<details2>..</2details>
</details>
</Produkt>
<Produkt>
<Produkt_Nummer>9</Produkt_Nummer>
<details>
<details2>..</2details>
</details>
</Produkt>
Ich will nun das XML File durchlaufen und den gesamten Block, welcher doppelt vorkommt, löschen. Leider läuft dein mechanismus auch auf einen Out of Memory.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
open(my $fh_in, '<', "input.xml") or die "... : $!"; open(my $fh_out, '>', "output.xml") or die "... : $!"; # Produkte, die schon ausgegeben wurden my %Produkt_nummer_gesehen; # lese immer einen kompletten Produktdatensatz ein local $/ = "</Produkt>"; while (my $prod = <$fh_in>) { my $pn = extract_produkt_nummer($prod); next if $Produkt_nummer_gesehen{$pn}++; print $fh_out, $prod; }
2013-07-16T09:48:08 clms
QuoteErsteres geht zeilenweise durch die Datei, letzteres liest erst die gesamte Datei ein
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
{ package IterTest; use overload '<>' => \&iterator, fallback => 1; my $x = 0; sub new { return bless {}, shift; } sub iterator { print "Angefragt!\n"; if ($x++ < 10) { return $x; } else { return undef; } } } my $test = IterTest->new(); for my $num (<$test>) { print "$num\n"; }
2014-02-06T09:24:57 MuffiIch könnt mir jetzt vorstellen, dass er das bei einem Iterator auch kapiert.
reneeWas hast Du denn bisher probiert? Wo hast Du Probleme? Wir wollen hier helfen und nicht unbedingt ganze Programme schreiben.
my ($pn) = $prod m/<RegulärerAusdruck>/;
perldoc perlsyn...
The foreach loop iterates over a normal list value and sets the variable VAR to be each element of the list in turn.
...
The foreach keyword is actually a synonym for the for keyword, so you can use either.
...
for(;<$fh>;){}
1 2 3 4 5 6 7 8
#!/usr/bin/perl use warnings; use strict; use Tie::File; my @array; tie(@array, 'Tie::File', "file.txt") or die; print "$array[13]\n";
QuoteThe file is not loaded into memory, so this will work even for gigantic files.