in reply to PERL/XML

I apologize for the poorly written post. Maybe I can clear it up a bit. I'll resend my situation and question. The included XML is only a snippet of the real XML code. I just wanted to give an example of what I was dealing with. I hope the Perl is now more legible. I know there has to be a way to get the info from between the brackets.

Hello - Below you'll find a Perl script and XML code. The .pl file reads from the .xml file, then turns the XML info into an HMTL document. The script works, but it works too well. I'm trying to extract the information from between the < ! [ CDATA ] > tags. But instead it retrieves everything (the < ! [ CDATA ] > and the info within it). How can I have the script pull just the info from within the brackets?

XML:

<artikle> <! [ CDATA [Test tittle ] ] > </artikle> <ingres> <! [ CDATA [Test ingres ] ] > </ingres> <url> <! [ CDATA [Test url ] ] > </url

PERL:

#!/usr/bin/perl # This script retrives an xml formatted news feed document and # generates a HTML file based on a tamplate file # # Format of the input should be: # <article>Some article # <title>Some Title</title> # <ingress>Some text</ingress> # <url>Some url</url> # </article> # # Modify vars in the config part to match your environment # # asbjorn@linux-directory.com, Oct. 2000 # ###### CONFIG START # Input format $article_del = "artikkel"; $title_del = "tittel"; $url_del = "url"; $ing_del = "ingress"; # Input format end $template = "template.txt"; ### Template HTML file. $html = "out.html"; ### Name & path of HTML file to be generated $weburl = "http://www.filmguiden.no/xml/filmguiden.xml"; ### URL of do +cument to be retrived $maxarticles = 5; ### Max no. of articles to be buildt. Must match tem +plate file $cgi = 1; ### Set if the script is to be run from a browser ###### CONFIG END #### MODULES USED use HTTP::Request; use LWP::UserAgent; use CGI; #### MODULES END $q=new CGI; print $q->header() if ( $cgi ); print $q->h3("$ver") if ( $cgi ); print "Henter $weburl"; print "<br>" if ( $cgi ); $ua = LWP::UserAgent->new; $request = HTTP::Request->new(GET => "$weburl"); $response = $ua->request($request); %hash = %{$response}; $content = $hash{_content}; $msg = $hash{_msg}; if ( $msg ne "OK" ) { print "Could not contact web server!\n"; exit 2; } print "Fetched $weburl\n"; print "<br>" if ( $cgi ); open(IN,"$template") || die "Failed to open $template: $!\n"; open(OUT,">$template.tmp") || die "Failed to write to $template.txt: $ +!\n"; while(<IN>) { print OUT; } close(OUT); close(IN); print "Generating HTML file:\n"; print "<br>" if ( $cgi ); @art = split m#(<$article_del>|</$article_del>)#, $content; shift @art; pop @art; foreach $art ( @art ) { ($title) = $art =~ m#<$title_del>(.*)</$title_del>#; ($ingress) = $art =~ m#<$ing_del>(.*)</$ing_del>#; ($url) = $art =~ m#<$url_del>(.*)</$url_del>#; ($url) = $url =~ m#<a href="(.*)">#; $i++ if $title; last if ( $i > $maxarticles ); &writefile($i,"title",$title) if ( $title ); &writefile($i,"ingress",$ingress) if ( $ingress ); &writefile($i,"url",$url) if ( $url ); } rename("$template.tmp","$html") || die "Failed to write $html: $!\n"; print " ----: DONE :----"; sub writefile { my $num = shift; my $type = shift; my $text = shift; $st = "URL_$num" if ( $type eq "url" ); $st = "TITTEL_$num" if ( $type eq "title" ); $st = "INGRESS_$num" if ( $type eq "ingress" ); open(IN,"$template.tmp") || die "Failed to open $template: $!\n"; @in = <IN>; close (IN); open(OUT,">$template.tmp") || die "Could not write to $html: $!\n"; foreach ( @in ) { s/$st/$text/g; print OUT; } close(OUT); }

Replies are listed 'Best First'.
Re: Re: PERL/XML
by mirod (Canon) on Feb 20, 2001 at 02:11 UTC

    I hope you are still having formatting problems: your XML is still not valid, <![CDATA and]]> must be written as-is, without spaces.

    Anyway, using XML::Simple here is how you get the information:

    #!/usr/bin/perl use strict; use XML::Simple; my $xml= XMLin( \*DATA); my $artikle= $xml->{artikle}; $artikle=~ s/^\s*//s; $artikle=~ s/\s*$//s; print "article: $artikle\n"; __DATA__ <doc> <!-- you still need to wrap your XML in a +single root element --> <artikle> <![CDATA[Test tittle ]]> </artikle> <ingres> <![CDATA[Test ingres ]]> </ingres> <url> <![CDATA[Test url ]]> </url> </doc>

    You should actually avoid unnecessary line returns within the XML documents, they _are_ significant:

    <doc> <artikle><![CDATA[Test tittle ]]></artikle> <ingres><![CDATA[Test ingres ]]></ingres> <url><![CDATA[Test url ]]></url> </doc>

    Then you can get rid of the 2 lines that remove leading and trailing spaces.

    Note that I still can't figure out whether you real XML document includes only one article or several, in which case the format of the data as loaded by XML::Simple will change. As should your XML data actually (each article should be wrapped in a tag).

    Usually I use the following script to figure out what's going on and how XML::Simple digests my document:

    #!/usr/bin/perl use strict; use XML::Simple; use Data::Dumper; my $xml= XMLin( \*DATA); print Dumper( $xml); __DATA__ <my> document here, oh </my>

    So finally I think what you are looking for night be something like:

    #!/usr/bin/perl use strict; use XML::Simple; use Data::Dumper; my @fields= qw( title ingres url); my $xml= XMLin( \*DATA); foreach my $article (@{$xml->{artikle}}) # $xml is an ar +ray of hashes, each hash is an article { foreach my $field (@fields) # the key/value + pairs are element => content { print "$field: ", $article->{$field}, "\n"; } print "\n"; } __DATA__ <doc> <artikle> <title><![CDATA[Test tittle ]]></title> <ingres><![CDATA[Test ingres ]]></ingres> <url><![CDATA[Test url ]]></url> </artikle> <artikle> <title><![CDATA[Test tittle 2]]></title> <ingres><![CDATA[Test ingres 2]]></ingres> <url><![CDATA[Test url 2]]></url> </artikle> </doc>
      thank you mirod... would it be possible for you to place your suggestions into my code? i've been trying and can't seem to get it right... thanks!