Output folder content in XML file

Output folder content in XML file

Thursday, July 3rd, 2008 in PHP

xml output Usually in a Flash gallery the images are shown using an XML file generated by the server (in our case using PHP). So, how do you create that XML file used to output the contents of your images folder?

Starting with PHP 5, we have some new tools added that ease out work. One in particular is of interest and that’s SimpleXML. In plain english, it offers the possibility to convert XML to an object and that may be used later in the code with simple array iterators. More than that, it can also output XML valid code to generate XML files.

For this example, besides SimpleXML, we’ll need one more thing: a way to read the folder containing the images. And for that we have readdir. So the process will go like this: first we need to read the entire directory with readdir() and after that we need to generate the XML output using SimpleXML. Remember, SimpleXML is available in PHP starting with version 5, so make sure you have it installed on your server.

To check your PHP server version, simply create a file called phpinfo.php and inside it put only this: <?php phpinfo(); ?> – after that, upload the file on your web hosting service. Open your favourite web browser and point it at this file ( www.mywebaddress.com/phpinfo.php ). The first this you’ll see will be the server version ( something like PHP Version 5.x.x ). Remember to delete the file after you’re done.

Ok, so by now, PHP 5 is available and we can start working. The process is pretty simple and straight forward. In this example of ours, the point is to output in XML every image within a directory and for every image to store the file path along with the width and height of the image.

If we look at the PHP documentation for SimpleXML, we can see that the constructor takes as argument an XML declaration and that’s what we have stored in $xml_string variable. After that , we can start populating the XML with our own image files.

1
2
3
4
5
6
$xml_string = <<<xml
<?xml version="1.0" encoding="UTF-8"?>
<images>
</images>
XML;
$xml_generator = new SimpleXMLElement($xml_string);

Now that we started SimpleXML, it’s time to read the image folder. As I said before, we use readdir for that. This function will return every element within the folder provided, but it will not read any other folders included in that. Let’s see:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$path_to_image_dir = 'images'; // relative path to your image directory
if ( $handle = opendir( $path_to_image_dir ) )
{
    while (false !== ($file = readdir($handle)))
    {
        if ( is_file($path_to_image_dir.'/'.$file) )
        {
           list( $width, $height ) = getimagesize($path_to_image_dir.'/'.$file);
           $image = $xml_generator->addChild('image');
           $image->addChild('path', $path_to_image_dir.'/'.$file);
           $image->addChild('height', $height);
           $image->addChild('width', $width);
        }
    }
    closedir($handle);
}

As you can see in the code above, the image width and height are gathered by getimagesize(). After that, a new child is create in our XML ( $image ) and to that child we’re adding the image file details (path, width and height). Always remember when reading a folder with readdir to close the opendir() handle using closedir().

Ok now. We have our XML object stored in $xml_generator. We’ll only need to output it so that the XML file can be read. We can do that in two ways. One is to use this file as XML, the other one is to actually create an XML file. If we’ll use this file as XML, there are a couple of things needed to be done. First of all, this file must say ‘I’m an XML file’. To do that, we set an XML header to it, so that it will be identified by whatever script is calling it as an XML file:

1
2
header("Content-Type: text/xml");
echo $xml_generator->asXML();

As you can see, first we say that this file is XML and after that the XML output is added using echo. Now, from what I know, if you call in Flash a PHP file that has XML header and valid XML output, things might not work as expected. So we’ll actually need to set it an XML extension. To do that, we use .htaccess. I’m not going to get into .htacess explaining here, I’ll just tell you what to do.

First thing is to create a file called .htaccess. We’ll assume that the php file holding all the code above is called my_xml_file.php. Inside the newly created .htaccess file, put the following lines:

1
2
RewriteEngine On
RewriteRule ^my_xml_file.xml$ my_xml_file.php [L,nc]

Save the file and upload it on your web server /httpdocs directory. Make sure that the file has no name, just the .htaccess extension.

This will make all calls made for my_xml_file.xml to actually go to the PHP file. Now we have the XML header, XML content and XML extension all in order. When calling the XML file from your application, you’ll address the my_xml_file.xml not my_xml_file.php. To test the installation, after uploading to your web server the PHP and .htaccess file, open a browser and point it to the XML file name added to .htaccess ( ie: http://mydomain.com/my_xml_file.xml ). You should see the XML output from the PHP file, which means everything is ok.

Now, if what you need is to actually create an XML file from the PHP file, you’ll need to replace these lines:

1
2
header("Content-Type: text/xml");
echo $xml_generator->asXML();

with these ones:

1
2
3
$file = fopen('path_to_xml/myfile.xml','w');
fwrite($file, $xml_generator->asXML());
fclose($file);

For this to work, you’ll need to put the XML file into a writable folder ( chmod 777 ). Once the file is created, if you add new files to the images folder, don’t expect them to appear in the XML file because they won’t. You’ll need to run the php file again in order to generate the XML file one more time with the complete images list.

That will be all. Here’s the complete code and the download files.

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
<?php
$path_to_image_dir = 'images'; // relative path to your image directory
 
$xml_string = <<<xml
<?xml version="1.0" encoding="UTF-8"?>
<images>
</images>
XML;
 
$xml_generator = new SimpleXMLElement($xml_string);
 
if ( $handle = opendir( $path_to_image_dir ) )
{
    while (false !== ($file = readdir($handle)))
    {
        if ( is_file($path_to_image_dir.'/'.$file) )
        {
           list( $width, $height ) = getimagesize($path_to_image_dir.'/'.$file);
           $image = $xml_generator->addChild('image');
           $image->addChild('path', $path_to_image_dir.'/'.$file);
           $image->addChild('height', $height);
           $image->addChild('width', $width);
        }
    }
    closedir($handle);
}
 
header("Content-Type: text/xml");
echo $xml_generator->asXML();
?>

Was this useful? Show your support.

digg Output folder content in XML file

59 comments

  1. zack says:

    thanks ;)

    Can you make similar to output folder contains as mrss ?

    Here is info/spec about mrss –> http://en.wikipedia.org/wiki/Media_RSS

    thanks in Advance ;)

  2. Hi Zack,

    It could be made but most probably you should use a different approach. From what I see in the mrss specs, you must specify attributes like framerate, channels, duration etc. From what I know, you can’t read all that data using PHP so maybe you should store all that into the DB and generate the mrss on request. This is just a first idea, I haven’t made anything similar to your request yet but I’ll give it a deeper thought.

  3. Joey says:

    Is there a way to dig into the sub directories in the given directory? I’m looking for something like this, but I need to also look in the sub directories, and possible their sub directories. For example:

    /images contains 30 images and 3 directories
    /images/vacation contains 0 images and 2 directories
    /images/vacation/2007 contains 100 images and 0 directories
    /images/vacation/2008 contains 300 images and 1 directory
    /images/vacation/2008/memphis contains 100 images
    ….

    Like that. I have code similar to the above, but it only returns the 30 images in the current directory.

  4. Yes, it is possible. See here for more details on reading multi level directories. Please note that the class in the example I gave you also has a delete_directory method. You don’t need to call that one, only the read_directory in order to have all the files stored into an array.

  5. Joey says:

    Thanks, I’ll play with it when I get home. I’ll have to modify it a little cause I’m using it to create XML, but it looks good.

  6. Joey says:

    I ended up doing this. And it works really well. I use it for a media player.

    ‘ . “\r\n”;
    echo “\r\n”;

    foreach( new RecursiveIteratorIterator( new RecursiveDirectoryIterator(‘.’)) as $item)
    {
    if ( in_array( substr($item, -3), $extensions ) )
    {
    $song = str_replace(” “,”%20″,$item);
    $song = substr($song, 2);
    echo (‘ *LEADINGPATH*’ . $song . ”);
    echo “\r\n”;
    }
    }
    echo “”;
    ?>

  7. Joey says:

    Previous post removed some code. Last try.
    “‘ . “\r\n”;
    echo “\r\n”;

    foreach( new RecursiveIteratorIterator( new RecursiveDirectoryIterator(‘.’)) as $item)
    {
    if ( in_array( substr($item, -3), $extensions ) )
    {
    $song = str_replace(” “,”%20″,$item);
    $song = substr($song, 2);
    echo (‘ *LEADINGPATH*’ . $song . ”);
    echo “\r\n”;
    }
    }
    echo “”;
    ?>”

  8. Joey says:

    Oh well, you get the point. It creates a XML file.

  9. @Joey

    Just a little suggestion. Don’t use a class like this:

    foreach( new RecursiveIteratorIterator( new RecursiveDirectoryIterator(’.’)) as $item)

    because each time the foreach makes a loop into your result, the class gets called and it very bad practice to do so. Instead assign the result from your class to a variable and use the foreach on it.

  10. Joey says:

    Oh, ok. Being new to PHP could you provide a small example.

  11. @Joey

    I don’t know if this example will work in your code, it’s just to make an idea.

    < ?php

    $files_in_folder = new RecursiveIteratorIterator( new RecursiveDirectoryIterator('.'));

    foreach ($files_in_folder as $file)
    {
    if ( in_array( substr($item, -3), $extensions ) )
    {
    $song = str_replace(” “,”%20″,$file);
    $song = substr($song, 2);
    echo (' *LEADINGPATH* ' . $song );
    echo '\r\n';
    }
    }

    ?>

  12. mike says:

    i have been trying to use this code. I have an xml file called ‘gallery’ and i wanted to write to it images file names generated by your code. I have failded to do so. I do not see any where in your code what the xml file name is.

    regards

    mike

  13. Hi Mike,

    The script above outputs the folder content as XML. It doesn’t create an xml file. To access the folder content as XML, from your script you need to point the php file not gallery.xml. This way, every time you add files to the folder, the script outputs all content. You could improve the code by creating a cache xml file and maybe run the above php file to create the xml file using a cron job.
    To point to gallery.xml and use the php file to generate the xml, you could create a rewrite rule using the .htaccess file like so:

    RewriteRule ^gallery.xml$ the_php_file_creating_the_xml_output.php

  14. Steve says:

    I’ve been looking for this exact script. But when I test it I get and error.
    Fatal error: Cannot instantiate non-existent class: simplexmlelement in /homepages/13/d238905384/htdocs/gallery/xml_test/index.php on line 16
    Please help!

  15. Hi Steve,

    My guess is that your server uses PHP4. The script above uses a class available in PHP5 and that’s the reason you get that error.

    Please test the PHP version your server uses. To do that, create a file called for example phpinfo.php and write in it :
    < ?php
    phpinfo();
    ?>

    Upload the file on your server and then open it using a browser. On top of the page you will see the version your server is using. If it’s less that PHP5, that’s your problem. To solve it you’ll need to contact your web hosting provider.

  16. Darren says:

    I am wondering how to set this up to generate only

    Thanks

  17. Darren says:

    the code was deleted:

    gallery
    image url=”image.jpg” /
    image url=”image 2.jpg” /
    image url=”image 3.jpg” /
    image url=”image 4.jpg” /

    gallery

  18. Well, you could try it like this:

    Replace this:

    $image->addChild(‘path’, $path_to_image_dir.’/’.$file);
    $image->addChild(‘height’, $height);
    $image->addChild(‘width’, $width);

    With this:

    $image->addAttribute( ‘url’ , $path_to_image_dir.’/’.$file );

  19. P feaT says:

    Can this code be used to create an automatic XML file for a folder containing mp3 files ??
    I mean if I modify the code to get the list of tracks…? Then I would be able to use it for my xml driven flash player..

    Regards

  20. Yes, it can be used for that but you’ll have to remove some code that was written for images. I mean these lines:

    list( $width, $height ) = getimagesize($path_to_image_dir.’/’.$file);

    $image->addChild(‘height’, $height);
    $image->addChild(‘width’, $width);

    Try it out. Let us know what you managed to achieve.

  21. Manji says:

    How can i save this, into an external xml file?

  22. Remove these lines:
    header(“Content-Type: text/xml”);
    echo $xml_generator->asXML();

    And instead add:

    $file = fopen(‘path_to_xml/myfile.xml’,'w’);
    fwrite($file, $xml_generator->asXML());
    fclose($file);

    Make sure that the folder and xml file (if you already created it) are writable ( chmod 777 ).

  23. Manji says:

    Hi,
    Thank you for your Help!
    Can I change the xml output, that it shows the newest pics first?
    Sorry for my bad english

  24. In order to obtain that, try filemtime(). See more info about it here.

    The idea is that you’ll store the folder content into and array having as keys the timestamp returned by filemtime() for each file. After that, use krsort() ( more info here ) to sort the array in reverse using the keys.

    This is just an idea. You’ll need to try it out and see what comes out.

  25. YhwhDesign says:

    I need to know how to output the following xml structure using php to do so, getting its data from mysql database table.

    Gallery 1
    Image 1
    Image 1
    Image 1
    Image 1
    Test 1

    Gallery 2
    Image 1
    Image 1
    Image 1
    Test 2

    basically I want the php script to output the data from the mysql database and have it format the
    xml script so that it will list all images that have the name gallery 1 in their row, and the images that
    have gallery 2 in their row would be listed under the tag or in between the tag gallery 2.

    please help someone…please

    thanks

    • What you could do for what you need to achieve is select the galleries from your database and then for each gallery add the images. I’ll assume you have all the data stored into your database:

      $galleries = mysql_query(“SELECT … FROM my_galleries”);
      while( $g = mysql_fetch_assoc($galleries) )
      {
      $gallery= $xml_generator->addChild($g['gallery_name_column']);
      $images = mysql_query(“SELECT … FROM my_images WHERE gallery_id = ‘”.$g['gallery_id'].”‘”);
      while( $i = mysql_fetch_assoc($images) )
      {
      $gallery->addChild($i['image_name'], $i['image_path']);
      }
      }

      I hope this solves your problem. This code should replace the whole if ( $handle… statement

  26. Nadine says:

    I will be trying the code out for extracting the mp3. I will let you know as well if it works. Thanks again!

  27. Nittin says:

    hi constantin. i have the same issue as joey had but i can’t seem to understand how he went about solving it. how could i use your recusive folder list to get an xml file that spans multiple folders? please help…..

  28. Done4who says:

    url of php: http://www.bizioinc.com/xmlgallery/load/graphics/xmlgenerator.php

    Heavily modified but it doesn’t read and output in numberical or alphabetical. It seems to read randomly. How can I sort the list as it writes to xml?

  29. derek says:

    When I add this line to .htaccess it crashes my website in that no pages will work.

    RewriteRule ^my_xml_file.xml$ my_xml_file.php [L,nc]

    What’s wrong with this line?

  30. @derek
    Quite nothing. It’s a simple rewrite rule. I didn’t had any trouble using it on my server. I use this mainly for captcha files where you have to call image.php for example but it looks lousy and I use rewrite and set it for image.jpg.

    @Done4who
    You could try constructing an array with the files returned when reading the folder (inside while) and after that sort the resulting array after you read the folder ( use arsort() or asort() – read documentation first to understand how each works ).

Leave a comment