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. Ian.J.Gough says:

    Great work just what i was looking for many thanks, : )

  2. Matt says:

    Is there a way to make it alphabetical? This does not seem to return an alphabetical list.

  3. Hi I need to do almost the samething but I don’t know how to include the CDATA-section tag out to the xml file.
    Can you help me to find out how to do it?
    Thanks,
    Samy

  4. Ziemowit says:

    Hello
    Great tutorial. This is very usefull knowledge. Thanks!
    But I have question about sorting with xml_generator.
    For example how to sort records in output xml file.
    When I upload new file to my directory i would like to have it on the begining of my xml list.
    And how to sort records in xml by name.
    If You woudl like to send me some anwsers or links where i could find some informations I would be greatfull.
    Regards.
    Ziemowit

    • Hi Ziemowit,

      When reading a directory, files are returned in the order they are stored by the filesystem. After reading the folder contents, the file is added to XML. One idea to sort your files by name is to first read the whole directory, store all filenames into an array, sort that array and after that populate the XML. About showing the last uploaded file first, you could use fileatime() for sorting in the array above.

      • Ziemowit says:

        Hi Constantin

        Thanks for Your reply.
        I get the idea. Now I’ll try to make it work. I found on the internet that meny people are looking for sorting xml knowledge. Some of them use xsl transformations but it brings more complications. I think the best way to do it, is that witch You suggested. To sort array before outputing xml. Maby You could find some time and write tutorial on that ;)

        Regards

  5. samy says:

    Great !
    I like it and it works fine.
    But, how can I add a CDATA-section?
    Can you add the code portion for that please?
    Thank you so much.

    • Hi samy,

      Sorry for the delay. I’ve been very busy. Looks like there’s a bigger problem regarding cdata. Here’s a possible solution: http://blog.evandavey.com/2008/04/how-to-fix-simplexml-cdata-problem-in-php.html
      When I have the time I’ll dig into it myself and see how this can be solved. As a note, I haven’t tested the above solution.

      • Samy says:

        I found the solution and it was so simple, the only thing I am looking now is to get them sort out. But almost there.
        I hope some is looking for this and have the sorting solutin, Thanks.

        SetItem(“Videos/Compartir_de_Jesus/$file”, “Thumbs/$file_jpg”, “”,”",”",”$file”,”$file”,”Presione y vea: $file”);
        }
        }

        // Write the XML File to a file.
        $fp = fopen(‘Alejandro_B_01.xml’, ‘w’);
        fwrite($fp, $myfeed->output());
        fclose($fp);

        class RSSFeed {
        // VARIABLES
        // channel vars
        var $channel_url;
        var $AlbumData;
        // image
        var $image_url;
        // Items
        var $Items = array();
        var $nrItems;
        // FUNCTIONS
        // constructor
        function RSSFeed() {
        $this->nrItems=0;
        $this->channel_url=”;
        $this->channel_AlbumData=”;
        }
        // set channel vars

        function SetChannel($url, $AlbumData) {
        $this->channel_url=$url;
        $this->channel_AlbumData=$AlbumData;
        }
        // set image
        function SetImage($url) {
        $this->image_url=$url;
        }

        // set Item
        function SetItem($url, $Thumb, $File, $FileInfo, $Link, $Name, $Description, $ToolTips) {
        $this->Items[$this->nrItems]['url']=$url;
        $this->Items[$this->nrItems]['Thumb']=$Thumb;
        $this->Items[$this->nrItems]['File']=$File;
        $this->Items[$this->nrItems]['FileInfo']=$FileInfo;
        $this->Items[$this->nrItems]['Link']=$Link;
        $this->Items[$this->nrItems]['Name']=$Name;
        $this->Items[$this->nrItems]['Description']=$Description;
        $this->Items[$this->nrItems]['ToolTips']=$ToolTips;
        $this->nrItems++;
        }
        // output feed
        function Output() {
        $output = ”.”\n”;
        $output .= ”;

        //for($k=0; $knrItems; $k++) {

        //};

        for($k=0; $knrItems; $k++) {
        $output .= ”;

        $output .= ‘Items[$k]['Thumb'].’”>’.”\n”;
        $output .= ‘Items[$k]['url'].’”>’.”\n”;
        $output .= ”.$this->Items[$k]['File'].”.”\n”;
        $output .= ‘Items[$k]['Link']. ‘”>’.”\n”;
        $output .= ‘Items[$k]['Name'] . ‘]]>’.”\n”;
        $output .= ‘Items[$k]['Description'] . ‘]]>’.”\n”;
        $output .= ‘Items[$k]['ToolTips'] . ‘]]>’.”\n”;

        $output .= ”.”\n”;
        };
        $output .= ”.”\n”;
        return $output;
        }
        };

        ?>

  6. Jonathan says:

    In order to make an itunes-store-compliant podcast, you need:

    <?xml version="1.0" encoding="UTF-8"?>
    <rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd&quot; version="2.0">

    then the rest of the xml output.

    But as $xml_result = $xml_generator->asXML(); won’t let you do that, here’s the workaround:

    $xml_result = $xml_generator->asXML();  
    $xml_LeftHandSide = '<?xml version="1.0" encoding="UTF-8"?><rss  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"  version="2.0">';  
    $xml_RightHandSide = substr($xml_result, 22);  
    echo $xml_LeftHandSide . $xml_RightHandSide . "</rss>";

    et voila! feedvalidator and itunes are happy.

    If anyone knows a better way, please let me know. Thanks!

  7. topi says:

    super! thanks!

  8. Nuno says:

    great tutorial!
    thanks so mutch for that and very well explained, in my case i just need on more thing
    is to read sub-folders with images, can you explain me how?
    best regards

  9. Will says:

    Hey, great post. Do you think this could be adapted for video as well? If so could you suggest where and how I should start?

    Cheers

  10. MikeyKs1 says:

    This works fine in IE but is NOT in Firefox because it does not sort. Sort by date or file name would be better on the output so that it could be used in the iTunes store. Firefox displays the XML file as written and this returns the XML in the order in which they are stored by the filesystem.

  11. Nicolaj Hansen says:

    Hey, i need something kind of that but instead of this :

    images/sunset.jpg
    800
    600

    i will need something like this:

  12. Bhargav says:

    Hey, great work it works good…………………………

    I need the output to save in separate(individual) XML file…………..is it possible……………plz help me out ……..thanks in advance

  13. Bhargav says:

    Thanks dude………………

    I got the output ………i used XMLWriter() to store the output in an xml file dynamically………………its working……….

  14. ninjes says:

    Hello!

    Your script is working fine! I am trying to modificate him to make xml file looking like this:

    But I am newbie at php, can anybody help me?

  15. chieftan says:

    between the path tags, i need to add .
    How can the “” be added?

  16. chieftan says:

    between the path tags, i need to add content src =”this is the source name which I get.jpg” .
    How can the content src =, and the quotes be added?

  17. dan says:

    It looks like you have to use a relative path…can this be used to read images in a directory with an absolute path? Only reason I ask is because the website I am working on is on a windows server and won’t allow installation of php. So I have another computer with linux installed and php5. Hoping to point the script to the folder of images on the site using the actual direct url like: http://www.example.com/images

Leave a comment