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

hey guys thanks for reading.

listen, i am a designer-idiot with a simple problem: i am trying to write a perl script that will generate an xml file based on the contents of a directory. the xml file will then be used in flash for a portfolio site.

basically, i will have a folder full of jpeg's, i want the perl script to generate the xml for flash so that the only thing i have to do to change out the images in flash is to replace the files in the directory.

the only info i really need in the xml file is an id attribute for the files (ie image1, image2 etc) and the url of each image.

so the xml could look like this:

<site> <item id="1" imageURL="/images/image1.jpg" /> <item id="2" imageURL="/images/image1.jpg" /> </site>

i found a perl script that works great, but i cant for the life of me figure out how to get the URL attribute (hey, i'm a designer-idiot, right?)

anyways, here is the perl code i am currently mangling:

#!/usr/bin/perl # -- Perl Dynamic XML directory Content Generator_by SUP@ -- # -- # This script is designed to make a dynamic XML file to be used with +flash # out of a directory that holds jpg files. I use this so my client m +ay simply # upload files into a ftp directory and the flash page automatically +gets # updated. This is the first time i give code to anyone on the net. # hope you enjoy it. You must have a little knowledge of perl to make + this # work for you. I commented as much as I could. # -- # By : SUP@ mtlelite@hotmail.com # -- print "content-type: text/html\n\n"; # show Load data ... print "<html><body>"; print "<h1>Loading data...\n"; print "</h1></body><html>"; # open xml file to write open(FIL,">../pub/database.xml"); # lock the file flock(FIL,2); # XML intro print FIL "<?xml version= 1 ?>\n"; # xml category print FIL "<categoryName>\n"; # create index var local $t; $t=0; # open image directory to create xml from opendir(HOMEDIR, "../images/") || die ("Unable to open directory"); # loop thru array of directory while ($filename = readdir(HOMEDIR)) { #parce the . .. things from directory array and for jpgs only if($filename ne "." && $filename ne ".." && substr($filename,l +ength($filename)-4,4) eq ".jpg") { #increment index $t++; my $nfile; # create and print the jpg xml item into xml file $nfile=substr($filename,0,length($filename)-4); print FIL "<pic$t name=\"$nfile\"></pic$t>\n"; } # loop } closedir(HOMEDIR); # finish off xml file with end category and close the file print FIL "</pics>\n"; flock(FIL,8); close(FIL); # -- # By : SUP@ mtlelite@hotmail.com

please help an idiot out. in the meantime i will be reading my ass off over at learn.perl.org and trying to end my lamness.

peace!
decerebrate

Replies are listed 'Best First'.
Re: creating an xml file from perl
by ikegami (Patriarch) on Apr 13, 2005 at 23:11 UTC

    Instead of
    print FIL "<categoryName>\n";
    you'd use
    print FIL "<site>\n";

    Instead of
    print FIL "</pics>\n";
    you'd use
    print FIL "</site>\n";

    Instead of
    print FIL "<pic$t name=\"$nfile\"></pic$t>\n";
    you'd use

    use URI::Escape qw( uri_escape ); my $escaped_file = $nfile; # Convert the file name to a URL. $escaped_file = uri_escape($nfile); # Escape the URL for use in an HTML attribute. #uri_escape already removes & and ". #$escaped_file =~ s/&/&amp;/g; #$escaped_file =~ s/"/&quot;/g; print FIL "<item id=\"$t\" name=\"$escaped_file\" />\n";

    btw, it checks for .jpg in lowercase. You may want to replace
    substr($filename, length($filename)-4, 4) eq ".jpg"
    with
    lc(substr($filename, length($filename)-4, 4)) eq ".jpg"
    or the simpler
    lc(substr($filename, -4)) eq ".jpg"
    in case file is named SOMETHING.JPG.

    Update: Added uri escaping.

      thank you so much.

      when i replace with this:

      my $escaped_file = $nfile; $escaped_file =~ s/&/&amp;/g; $escaped_file =~ s/"/&quot;/g; print FIL "<item id="$t" name=\"$escaped_file\" />\n";

      i get a server error

        I forgot to escape some of the quotes in the print statement. Fixed:

        my $escaped_file = $nfile; $escaped_file =~ s/&/&amp;/g; $escaped_file =~ s/"/&quot;/g; print FIL "<item id=\"$t\" name=\"$escaped_file\" />\n";

        What's the server error? My guess is that the server is complaining that it can't find the files, because you are not including the correct path to the file.

        the lowliest monk

      Escaping would be safer using URI::Escape:
      use URI::Escape; my $escaped_file = uri_escape($nfile);

      Flavio (perl -e "print(scalar(reverse('ti.xittelop@oivalf')))")

      Don't fool yourself.
        Shoot, I forgot about that. Actually, it needs to be URI escaped and HTML value escaped. However, since uri_escape removes '"' and '&' by default, HTML value escaping is a no-op.
Re: creating an xml file from perl
by tlm (Prior) on Apr 14, 2005 at 01:04 UTC

    Try replacing the following two lines and everything below them:

    # open xml file to write open(FIL,">../pub/database.xml");
    with
    my $img_dir = '../images'; opendir HOMEDIR, $img_dir or die "opendir failed: $!\n"; my @filenames = readdir HOMEDIR; closedir HOMEDIR or die "closedir failed: $!\n"; open FIL, '>', '../pub/database.xml' or die "open failed: $!\n"; flock( FIL, 2 ) or die "flock failed: $!\n"; print FIL <<EOXML; <?xml version="1.0"?> <site> EOXML { my $path_to_imgs = '/images'; my @f = @filenames; # @f will be destroyed my $t = 1; use HTML::Entities; for my $filename ( map encode_entities( $_ ), grep s/\.jpg$//i, @f ) { print FIL qq(<item id="$t" imageURL="$path_to_imgs/$filename" />\n +); $t++; } } print FIL "</site>\n"; flock FIL, 8 or die "flock failed: $!\n"; close FIL or die "close failed: $!\n";
    If the line requesting use HTML::Entities gives you trouble...

    Update: Fixed closedir bug; added entities encoding (following ikegami's suggestion).

    the lowliest monk

      Guys,

      Thanks so freaking much, i've got it under control now!

      *bows to the awesomest of monastics*

      w00t! :)

Re: creating an xml file from perl
by Cody Pendant (Prior) on Apr 13, 2005 at 23:48 UTC
    if($filename ne "." && $filename ne ".." && substr($filename,length($filename)-4,4) eq ".jpg")

    1) Is there such a thing as a file which ends ".jpg" and also equals "."? No, so you don't need those clauses, just the ".jpg" one. Nor do you need the length in order to do a negative substring. But as noted above, checking whether it matches /\.jpg$/i is a better test.

    2) You're having trouble figuring out the URL? We can't help you because we don't know your server. It could be anything. If your server is "metlelite.com" and the images are in "public_html/foo/bar/images/" then the URL is probably "metlelite.com/foo/bar/images/filename.jpg". Trial and error should sort that out!

    3)

    print FIL "<pic$t name=\"$nfile\"></pic$t>\n";
    would be a lot easier on the eye if you used the qq() function, as in
    print FIL qq(<pic$t name="$nfile"></pic$t>\n)";

    4) It would probably be better to use an XML module, in the long run. Your output is technically XML but all kinds of errors and incompatibilities could creep in and you'd never know because you're rolling it by hand.



    ($_='kkvvttuu bbooppuuiiffss qqffssmm iibbddllffss')
    =~y~b-v~a-z~s; print

      greetings

      i apologize if i have been unlear

      what i do not know how to do is to have perl insert the path of the file into the xml document as an attribute ie

      <imageURL="/images/image1.jpg" />

      i have never laid eyes upon perl before today

        You just stick the literal "/images/" in there. A-like so:
        print qq(<item id="$t" imageURL="/images/$filename" /> \n);
        And if you really meant to chop off the extension, you'd do
        print qq(<item id="$t" imageURL="/images/$nfile" /> \n);
Re: creating an xml file from perl
by cbrandtbuffalo (Deacon) on Apr 14, 2005 at 00:19 UTC
    Replace the code in your while with this and see if it's closer to what you're looking for:
    my $t = 1; # loop thru array of directory while ($filename = readdir(HOMEDIR)) { #parse the . .. things from directory array and for jpgs only if($filename ne "." && $filename ne ".." && substr($filename,length( +$filename)-4,4) eq ".jpg") { #increment index my $nfile; # create and print the jpg xml item into xml file $nfile=substr($filename,0,length($filename)-4); print FIL "<pic$t id=\"$t\" name=\"/images/$filename\"></pic$t>\ +n"; } $t++; # loop }