falco has asked for the wisdom of the Perl Monks concerning the following question:

This node falls below the community's minimum standard of quality and will not be displayed.

Replies are listed 'Best First'.
Re: PERL/XML
by mirod (Canon) on Feb 19, 2001 at 23:45 UTC

    A pointy bracket does not an XML document make!

    <!CDATA[ Test tittel ]> - <!CDATA[ test ingres ]> - <![CDATA[ http://www.test.com/test ]]>

    This is not XML. An XML document is something with a root element and nested elements, something like:

    <article> <title>Test tittel</title> <ingres>test ingres</ingres> <url>http://www.test.com/test</url> </article>

    You might even want to add an XML declaration at the top of your file, just to make things more clear, and because I see you hitting encoding problems fairly soon in your experiments:

    <?xml version="1.0" encoding="ISO-8859-1"?>

    Then as OeufMayo mentionned you should use an XML parser, at least it parses real XML as opposed to what your code seems to do (I can't tell considering the formatting).

    Now after reading your code maybe your document is really an XML document, and I just got confused by the formatting, but in any case, you should still use a parser. If you don't you are not parsing XML but an undefined subset of XML. That will bite you one day.

    From what I can guess from your code you use <artikle> as a delimiter between articles. This prevents you from using attributes to the artikle element. You also seem to be wrapping all your text in CDATA. Why not. But then <url>, which you also use a a delimiter is a valid string in any element.

    Do yourself a favor and use XML::PYX or XML::Simple. You will be surprised at how easy they are to use and you will know that you have done things right, instead of writing a dirty hack that will crash baddly when you start using it in production code.

Re: PERL/XML
by aardvark (Pilgrim) on Feb 20, 2001 at 00:30 UTC
    If you want to convert XML to HTML you may want to look at:
    Matt Sergeant's AxKit:
    http:://www.axkit.org
    The Apache XML Project
    http://xml.apache.org

    If you are trying to ramp up quickly on XML here are a few good links
    Archives of the perl-xml mailing list
    http://mailarchive.activestate.com/browse/perl-xml
    XML.com ( has lots of good articles)
    http://www.xml.com
    The World Wide Web Consortium (which maintains the standard)
    • XML - http://www.w3.org/XML/
    • XSL - http://www.w3.org/Style/XSL/
    • XSLT - http://www.w3.org/TR/xslt.html
    The XML Cover Pages
    http://www.oasis-open.org/cover/sgml-xml.html
    XMLHack
    http://www.xmlhack.com/

    You also may want to check out David Cross's new book Data Munging with Perl.
    It has a good section on XML & HTML parsers.
    You can even get it as an e-book, which is so cool.
    http://www.manning.com/cross/index.html

    Anyway, I hope this helps. Good Luck.

    Get Strong Together!!

Re: PERL/XML
by falco (Initiate) on Feb 20, 2001 at 01:05 UTC
    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); }

      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!
(redmist) Re: PERL/XML
by redmist (Deacon) on Feb 19, 2001 at 23:32 UTC
    Please wrap your code in <code> tags.

    redmist
    Silicon Cowboy