howieD Skrevet 25. januar 2010 Del Skrevet 25. januar 2010 (endret) Hey, Jeg har installert XML::Simple, og har lekt meg litt med dette de siste dagene. Det er ingen problemer med å parse en enkelt fil, men jeg ønsker å lese inn en mappe med 400 xml filer som alle skal parses en etter en. De har samme oppbygging, og derfor trenger jeg bare et script som leser en og en fil. Problemet er at følgende script ikke fungerer: #!/usr/bin/perl use XML::Simple; use Data::Dumper; $xml = new XML::Simple(keeproot => 1, searchpath => "../xml/"); # Sorterer filnavnet my @files = `ls -l ../xml/ | sort -t "-" -k3`; foreach $file (@files){ $data = $xml->$XMLin("$file"); print "Navn:\n$data->{body}->{content}\n"; } Følgende script fungerer: #!/usr/bin/perl use XML::Simple; use Data::Dumper; $xml = new XML::Simple(keeproot => 1, searchpath => "../xml/"); # Sorterer filnavnet my $filen = "XXX-12345678-112233445566-112233.xml"; $data = $xml->$XMLin("/home/hoved/Desktop/xml/$filen"); print "Navn:\n$data->{body}->{content}\n"; blir sprø! Noen som vet hvordan man kan parse alle xml filer i en enkelt mappe? OS: Debian Håper på raskt svar Endret 25. januar 2010 av Haavard82 Lenke til kommentar
gizzlon Skrevet 25. januar 2010 Del Skrevet 25. januar 2010 Du burde virkelig vurdere å bruke use warnings; use strict; det tar en del vanlige feil (perl.com intro) Har ikke XML::Simple tilgjengelig, men når jeg kjører koden din på bsd blir $file satt til snodige ting.. har du printa den ut? Lenke til kommentar
howieD Skrevet 25. januar 2010 Forfatter Del Skrevet 25. januar 2010 (endret) Du burde virkelig vurdere å bruke use warnings; use strict; det tar en del vanlige feil (perl.com intro) Har ikke XML::Simple tilgjengelig, men når jeg kjører koden din på bsd blir $file satt til snodige ting.. har du printa den ut? Da satte jeg på warnings og strict.. Resulatet er at jeg får følgende error på variablene: $xml, $file og $data: Global Symbol "<variabel nevnt ovenfor>" requires explicit package name at ./xmlscript.pl line xx" Det virker som at man da bare kan gi filnavnet direkte, og ikke ved hjelp av en foreach e.l ? Enig i det? Jeg fikk ikke de snodige tingene dine. Har du installer CPAN XML::Simple pakkene o.l? Var en del drit for å få installert alt det nødvendige. Men ja, det må da være en eller annen mulighet når vi er i 2010 til å parse flere XMl filer? lættis hvis ikke! Endret 25. januar 2010 av Haavard82 Lenke til kommentar
Wattengård Skrevet 27. januar 2010 Del Skrevet 27. januar 2010 Kan det være fordi $xml-objektet ditt ikke er muterbart? at du må lukke det eller reinitialisere det på nytt før du laster inn neste fil... Du må også initialisere variablene dine... "my $xml; my $file; my $data;" Og en annen ting jeg har lært av perl er at selv om et bibliotek heter "::Simple", så betyr det ikke nødvendigvis at det faktisk _er_ "simple" -C- Lenke til kommentar
howieD Skrevet 27. januar 2010 Forfatter Del Skrevet 27. januar 2010 (endret) Kan det være fordi $xml-objektet ditt ikke er muterbart? at du må lukke det eller reinitialisere det på nytt før du laster inn neste fil... Du må også initialisere variablene dine... "my $xml; my $file; my $data;" Og en annen ting jeg har lært av perl er at selv om et bibliotek heter "::Simple", så betyr det ikke nødvendigvis at det faktisk _er_ "simple" -C- Jeg har tatt hensyn til det du har skrevet, og laget et nytt script: #!/usr/bin/perl use warnings; use strict; use XML::Simple; use Data::Dumper; my $data; my $xml; my $files; my $file; $xml = new XML::Simple(keeproot => 1, searchpath => "../xml/"); my @files = `ls -1 ../xml/ | sort -t "-" -k3`; foreach $files (@files){ open FILE, ">", "../xml/$files" or die $!; print $data = $xml->XMLin("../xml/$files"); close(FILE); print "Output er: $data->{body}->{main}->{info}->{content}\n"; } Nå får jeg error: Ran out of memory for input buffer at /usr/lib/perl5/XML/Parser/Expat.pm line 469. Noen idèer? Jeg har forsøkt å søke på denne feilen på google, uten å finne noe. Virker nesten umulig dette! PS! Når jeg kommenterte ut denne linjen: "# print $data = $xml->XMLin("../xml/$files");" Så kjører scriptet, og gir meg en linje i terminalen for hver fil den har i arrayen @files: "$VAR1 = undef; $VAR1 = undef; $VAR1 = undef; $VAR1 = undef; $VAR1 = undef; $VAR1 = undef; $VAR1 = undef; $VAR1 = undef;" osv..... Det virker som at det er her feilen ligger: "XMLin("../xml/$files");" Om jeg skriver navnet på en XML fil inni XMLin() vil filen parses korrekt, det er altså det å gi navnet via en variabel som feiler virker det som? Endret 27. januar 2010 av Haavard82 Lenke til kommentar
Wattengård Skrevet 27. januar 2010 Del Skrevet 27. januar 2010 Det var ikke filen jeg tenkte på om du lukket eller ikke, men XML-objektet. Hiv på en linje som sier "print $files;" inne i loopen og sørg for at du får ut korrekte filnavn. Iterering og variabler og referanser og pekere og og og og... i perl... *sukk* -C- Lenke til kommentar
howieD Skrevet 27. januar 2010 Forfatter Del Skrevet 27. januar 2010 (endret) Det var ikke filen jeg tenkte på om du lukket eller ikke, men XML-objektet. Hiv på en linje som sier "print $files;" inne i loopen og sørg for at du får ut korrekte filnavn. Iterering og variabler og referanser og pekere og og og og... i perl... *sukk* -C- Jeg har laget en print $files inni loopen, og jeg får ut riktige filnavn. Dukker opp en feilmelding om at filen ikke finnes når jeg bruker den samme variabelen inni XMLin(). Jeg har forsøkt å skrive mappestien osv uten at det hjelper. Det er fryktelig fryktelig rart! Jeg er redd jeg ikke helt ser hva du mener med resten av det du skriver. Kunne du være så kjempesnill å skrive om scriptet for meg ? Jeg lærer fort, og vil skjønne vitsen. Det vil sikkert være veldig nyttig for andre som søker opp dette emnet senere Endret 27. januar 2010 av Haavard82 Lenke til kommentar
Wattengård Skrevet 28. januar 2010 Del Skrevet 28. januar 2010 Jeg er nok ikke den rette til å skrive om scriptet til deg da jeg hater perl intenst Jeg har brukt perl endel iforbindelse med xmltv (se sig) og har det langt oppi halsen. Når jeg har lest xml har jeg derimot brukt LibXML. Iflg http://search.cpan.org/~grantm/XML-Simple-...mple.pm#XMLin() så kan du sette mapper hvor den skal lete etter XML-filer, for deretter å ikke benytte den fulle banen i XMLin(). hva om du prøver å gjøre det på den måten? -C- Lenke til kommentar
quantum Skrevet 28. januar 2010 Del Skrevet 28. januar 2010 (endret) Jeg er redd jeg ikke helt ser hva du mener med resten av det du skriver.Kunne du være så kjempesnill å skrive om scriptet for meg ? jeg tror han mener du skal opprette XML::Simple inni loop'en, altså foreach blablabla { $xml = new XML::Simple(keeproot => 1, searchpath => "../xml/"); open FILE ... osv. } hvis XML::Simple er immutable betyr det at egenskapene, f.eks. hvilken fil som skal parses, ikke kan endres på en gitt instans. skal du parse en ny fil må du opprette en ny instans. eventuelt er det sånn at et eller annet må initialiseres før eller etter at du leser inn ny fil. det står vel i tilfelle i dokumentasjonen? selv om du har satt på strict og postet hvilke meldinger du da får kan jeg ikke se at du egentlig har fortalt hva du mener med "virker ikke". Får du feil, krasj, printes samme navn ut for hver loop eller hva? du skriver også at du får loopen til å gå rundt om du kommenterer ut kodelinja som faktisk parser fila, og at filnavnet i $files er riktig. prøv å opprette ny instans av xml-objektet inni løkka og se om det hjelper. eventuelt prøv en variant av det første skriptet ditt, men med to statiske filnavn istedenfor ett. da får du sjekket dette med immutability og initialisering, uten at du bruker foreach. Endret 28. januar 2010 av quantum Lenke til kommentar
quantum Skrevet 28. januar 2010 Del Skrevet 28. januar 2010 foreach $files (@files){ open FILE, ">", "../xml/$files" or die $!; print $data = $xml->XMLin("../xml/$files"); close(FILE); print "Output er: $data->{body}->{main}->{info}->{content}\n"; } ... PS! Når jeg kommenterte ut denne linjen: "# print $data = $xml->XMLin("../xml/$files");" ... Det virker som at det er her feilen ligger: "XMLin("../xml/$files");" Om jeg skriver navnet på en XML fil inni XMLin() vil filen parses korrekt, det er altså det å gi navnet via en variabel som feiler virker det som? Når jeg leser dette kommer jeg på et par ting til. fjern "print" fra print $data = $xml->XMLin("../xml/$files"); da har du ihvertfall rydda vekk en ting du egentlig ikke skal ha med i det ferdige scriptet, og dermed en feilkilde. tror ikke dette er problemet, men lurt å strippe vekk mest mulig. du skriver at du tror feilen ligger i kodelinja ovenfor her, siden det går rundt når du kommenterer ut denne. men det kan vel like godt hende at problemet ligger i xpath-linja hvor du printer ut Navn. xpath-søket går fint når det ikke er noe innhold å søke i, men du får faktisk en out-of-memory feil når du bruker xpath til å søke fram verdien du skal printe ut. feilen oppstår jo i Expat.pm - som jeg *gjetter* inneholder funksjon for å utføre xpath-søk i eksisterende (innleste og dom-parsede) dokumenter. for å verifisere dette kan du kanskje legge inn en liten debug-utskrift innimellom de andre linjene i foreach-loopen a'la "print "ok so far (1)"; blablabal; print "ok so far (2)"; blabla; osv. Eventuelt bruke en debugger. det hadde vært interessant å visst om du får feil allerede i første runde av loop'en, eller om du får out-of-memory feil først etter at det har gått bra noen omganger. isåfall ville jeg gjette at koden din leser inn og *legger til* nye xml-dokumenter i xml-objektet uten å ta vekk det som ligger der fra før, altså at dokumentet som xpath-søken kjøres i vokser for hver runde og til slutt blir så stort at minnet sprekker. Lenke til kommentar
quantum Skrevet 28. januar 2010 Del Skrevet 28. januar 2010 (endret) Denne fungerte for meg: #!/usr/bin/perl use warnings; use strict; use XML::Simple; use Data::Dumper; my $data; my $xml; my $file; my @files; $xml = new XML::Simple(keeproot => 1, searchpath => "../xml/"); opendir(DIR, "../xml"); @files = readdir(DIR); closedir(DIR); foreach $file (@files){ next if ($file eq "." or $file eq ".."); print $file . "\n"; $data = $xml->XMLin($file); print "Output er:" . $data->{opt}->{person} . "\n"; } 1. jeg fikk ikke kjørt i utgangspunktet i strict når @files ikke var deklarert. 2. omnavnet $files til $file, siden det er navnet på en fil og ikke en liste. 3. katalogparsinga di med ls osv. fikk jeg ikke til å gi noe fornuftig. print $file; inni loopen så ikke riktig ut når jeg kjørte dette. muligens kan du ha fått out of memory feil når du har prøvd å lese inn "." eller ".." som en xmlfil. mulig du skal legge på open og close igjen. 4. du trenger ikke ha med stiveien til fila når du åpner den iom. at root blir satt når du instansierer xml-objektet. (du må derimot ha med hele stiveien dersom du legger inn open FILE igjen. Edit: Gjetter at du ikke trenger iom. at det ikke er vist i eksemplene i dokumentasjonen. 5. jeg hater også perl nå. 6. EDIT: Det funker også med my @files = `ls -1 ../xml/ | sort -t "-" -k3`; chop(@files); det ser altså ut som du får med en newline i filnavnene som du må ta vekk. Endret 28. januar 2010 av quantum Lenke til kommentar
Wattengård Skrevet 28. januar 2010 Del Skrevet 28. januar 2010 5. jeg hater også perl nå. LOL! Velkommen i klubben -C- Lenke til kommentar
Terrasque Skrevet 3. februar 2010 Del Skrevet 3. februar 2010 (endret) Det er ingen problemer med å parse en enkelt fil, men jeg ønsker å lese inn en mappe med 400 xml filer som alle skal parses en etter en. Litt sent, og kanskje jeg har misforstått noe.. Men for x in *.xml; do script.pl "$x"; done burde vel klare den biffen fint? Endret 3. februar 2010 av Terrasque Lenke til kommentar
asicman Skrevet 3. februar 2010 Del Skrevet 3. februar 2010 Det er ingen problemer med å parse en enkelt fil, men jeg ønsker å lese inn en mappe med 400 xml filer som alle skal parses en etter en. Litt sent, og kanskje jeg har misforstått noe.. Men for x in *.xml; do script.pl "$x"; done burde vel klare den biffen fint? Eller hvis det er flere undermapper eller at noen av filnavnene har blanke i seg: find . -name '*.xml' -print0 | xargs -0 script.pl Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå