Schrift
[thread]10459[/thread]

XML-File parsen

Leser: 1


<< >> 8 Einträge, 1 Seite
Gast Gast
 2007-09-24 22:14
#99942 #99942
Hallo,

ich habe ein XML-File der Form

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<Buch>
<Titel>Titel 1</Titel>
<Autor>...</Autor>
<Beschreibung>...</Beschreibung>
</Buch>
<Buch>
<Titel>Titel 2</Titel>
<Autor>...</Autor>
<Beschreibung>...</Beschreibung>
</Buch>
<Buch>
<Titel>Titel 3</Titel>
<Autor>...</Autor>
<Beschreibung>...</Beschreibung>
</Buch>
...


in ein Array kopiert und möchte nun jedes Buch (mit all seinen Attributen und Werten) einzeln ausgeben. D.h. immer jeweils das ausgeben, was zwischen <Buch> und </Buch> steht.

Leider tue ich mich ein bißchen schwer damit, da folgender regulärer Ausdruck nur zeilenweise (also für jedes Element des Arrays) klappt und nicht für "zeilenübergreifende" Textblöcke:

Code: (dl )
1
2
3
4
foreach (@meinarray) {
if (/(<Buch>)(.*?)(<\/Buch>)/) {
print $2."\n";
}


Kann mir jemand weiterhelfen, wie ich das auf mehrere Zeilen des Arrays anwenden und die entsprechenden Matchings ausgeben kann? Danke schon mal. (Sorry, vermutlich Anfängerfrage.)

Jens
renee
 2007-09-24 22:43
#99943 #99943
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Verwende am besten ein Modul wie CPAN:XML::Simple oder für erfahrenere Perl/XML-Entwickler: CPAN:XML::Twig bzw. CPAN:XML::LibXML.

Tu' Dir das Parsen von XML nicht an. Das ist nicht so einfach wie es auf den ersten Blick aussieht. Spar' Dir die Zeit und verwende ein Modul...

Code (perl): (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
31
32
33
34
35
#!/usr/bin/perl

use strict;
use warnings;
use XML::Simple;
use Data::Dumper;

my $string;

{
    local $/;
    $string = <DATA>;
}

my $ref = XMLin( $string );
print Dumper $ref;

__DATA__
<root>
<Buch>
  <Titel>Titel 1</Titel>
  <Autor>...</Autor>
  <Beschreibung>...</Beschreibung>
</Buch>
<Buch>
  <Titel>Titel 2</Titel>
  <Autor>...</Autor>
  <Beschreibung>...</Beschreibung>
</Buch>
<Buch>
  <Titel>Titel 3</Titel>
  <Autor>...</Autor>
  <Beschreibung>...</Beschreibung>
</Buch>
</root>


Ausgabe
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$VAR1 = {
'Buch' => [
{
'Titel' => 'Titel 1',
'Beschreibung' => '...',
'Autor' => '...'
},
{
'Titel' => 'Titel 2',
'Beschreibung' => '...',
'Autor' => '...'
},
{
'Titel' => 'Titel 3',
'Beschreibung' => '...',
'Autor' => '...'
}
]
};


Dann kommst Du mit Referenzen (siehe perlreftut) in Berührung...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Gast Gast
 2007-09-24 23:00
#99945 #99945
Vielen Dank schon mal für den Tip, werde ich ausprobieren.

Grüße

Jens
nepos
 2007-09-25 10:26
#99960 #99960
User since
2005-08-17
1420 Artikel
BenutzerIn
[Homepage] [default_avatar]
Jo, nimm XML::Simple oder ähnliches und spiel dich da mal mit den Optionen. Damit kann man nämlich auch die oft etwas arg verschachtelten Datenstrukturen auf eine brauchbare Form eindampfen.
Gast Gast
 2007-09-25 19:17
#99980 #99980
XML::Simple funktioniert wirklich gut. Als relativer Perl-Neuling habe ich aber noch ein paar kleine Probleme, die gewünschten Daten dann aus dem Hash zu holen. Der Hash sieht (vereinfacht) so aus:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$VAR1 = {

'buch' => {

'12' => {
'titel' => 'Titel 1',
'beschreibung' => 'Beschreibung 1'
},

'34' => {
'titel' => 'Titel 2',
'beschreibung' => 'Beschreibung 2'
},

'150' => {
'titel' => 'Titel 3',
'beschreibung' => 'Beschreibung 3'
}

}

}


Ich möchte zu jeder Buch-ID den Titel und die Beschreibung ausgeben, nur eben nicht "manuell" wie folgt, sondern über eine foreach-Schleife.

Code: (dl )
1
2
3
4
5
6
print $ref->{'buch'}->{'12'}->{'titel'};
print $ref->{'buch'}->{'12'}->{'beschreibung'};
print $ref->{'buch'}->{'34'}->{'titel'};
print $ref->{'buch'}->{'34'}->{'beschreibung'};
print $ref->{'buch'}->{'150'}->{'titel'};
print $ref->{'buch'}->{'150'}->{'beschreibung'};



Ich weiß, bei Hashes gibt es die Funktion each, aber leider bekomme ich es nicht ganz hin, alle diese ID-Schlüssel zu durchlaufen. Für einen Tip/Ansatz wäre sehr dankbar.

Gruß
Jens
Linuxer
 2007-09-25 20:01
#99981 #99981
User since
2006-01-27
3881 Artikel
HausmeisterIn

user image
Verschachtelte Schleifen:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# wenn es nur 'buch' sein soll:
for my $typ ( qw( buch ) ) {
# wenn es alle typen sein sollen;
#for my $typ ( keys %$ref ) {

for my $idx ( keys %{$ref->{$typ}} ) {

for my $feld ( qw( titel beschreibung ) ) {

# wenn es alle typen sein sollen, fehlen noch einige abfragen, ob
# beispielsweise "titel" und "beschreibung" wirklich existieren
print $ref->{$typ}->{$idx}->{$feld}, $/;

}
}
}


empfohlene Lektüre: http://perldoc.perl.org/perldsc.html
Stichwort Hashes-of-Hashes
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
Gast Gast
 2007-09-25 20:19
#99982 #99982
Danke für die schnelle Antwort. Genau das hab ich gesucht :-)

Gruß
Jens
renee
 2007-09-26 10:20
#99998 #99998
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
übersichtlicher wird es noch, wenn man nicht immer mit der kompletten Referenz arbeitet...

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
# wenn es nur 'buch' sein soll:
for my $typ ( qw( buch ) ) {
my $buecher = $ref->{$typ};

for my $idx ( keys %$buecher) {
my $buch= $buecher->{$idx};

for my $feld ( qw( titel beschreibung ) ) {
print $buch->{$feld}, $/;
}
}
}


Wenn man "sinnvolle" Variablennamen verwendet, ist schon auf den ersten Blick ersichtlich, was gemacht wird...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
<< >> 8 Einträge, 1 Seite



View all threads created 2007-09-24 22:14.