Create Dynamic XML With PHP’s DOMDocument Class and Use It In Your Flash App
I was reading up on PHP’s DOMDocument Class recently and it’s really handly if you want to dynamically create HTML or XML files from PHP.
One practical application would be to create a simple dynamic image gallery in Flash without the need to manually maintain an XML file or database. All you’d need to do is mange the image files/directory. So I combined DomDocument with some of php’s directory functions to come up with the script below.
// relative path to the directory we'll be reading
$path = "images/";
// use the opendir function (the @ symbol will supress error messages and warnings)
$dir_handle = @opendir($path) or die("Unable to open $path");
// an array of filetypes we'll include in the output
$filetypes = array("jpg", "png");
// create a new XML document
$doc = new DomDocument('1.0');
// nicely format the output with indentation and extra space
$doc->formatOutput = true;
// create the root node (I've called it IMAGES)
$root = $doc->createElement('IMAGES');
$root = $doc->appendChild($root);
// run a while loop to read through the directory contents
while ($file = readdir($dir_handle)) {
// rawurlencode will replace any non-alphanumeric characters
// except hyphen(-) and underscore (_)
// with a percent (%) sign followed by two hex digits
// eg. a space ( ) will be replaced with %20
$file = rawurlencode($file);
// split the filename string so we can get the file extension
$split = explode(".", $file);
$ext = strtolower($split[count($split)-1]);
// if the extension matches a value in our $filetypes array we'll include it in the xml
if (in_array($ext, $filetypes)) {
// add a 'FILE' node
$item = $doc->createElement("FILE");
$item = $root->appendChild($item);
// comment out the line below if you don't want to include the relative path
$file = $path . $file;
// create a 'path' attribute on this FILE node and give it the $file value
$item->setAttribute('path', $file);
}
}
// close the directory
closedir($dir_handle);
// dumps the internal XML tree back into a string
echo $doc->saveXML();
The output would be something like:
<?xml version="1.0"?>
<IMAGES>
<FILE path="images/image1.jpg" />
<FILE path="images/image2.jpg" />
<FILE path="images/image3.jpg" />
<FILE path="images/image4.jpg" />
<FILE path="images/image5.jpg" />
</IMAGES>
You can then load this dynamic XML into Flash to create a gallery based on whatever images are in that directory.
The AS3 document class below simply loads the XML from the php script and then loads and display a single random image.
Assuming I’ve named the php script DirectoryXML.php and my directory structure looks something like:
- path/to/your/gallery/
- Main.swf
- DirectoryXML.php
- images/
- image1.jpg
- image2.jpg
- image3.jpg
- image4.jpg
- image5.jpg
package {
import flash.display.Bitmap;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
[SWF(width="800", height="600", frameRate="30", backgroundColor="#000000")]
public class Main extends Sprite {
private static const XML_SCRIPT:String = "DirectoryXML.php";
private var xmlLoader : URLLoader;
private var resultsXML : XML
private var imageLoader : Loader;
public var image : Sprite;
public function Main() {
this.xmlLoader = new URLLoader();
this.xmlLoader.addEventListener(Event.COMPLETE, this.onXMLLoaded);
this.xmlLoader.addEventListener(IOErrorEvent.IO_ERROR, this.onXMLLoadError);
try {
this.xmlLoader.load(new URLRequest(XML_SCRIPT));
}
catch (error:Error) {
trace("Error: " + error.message);
}
}
private function onXMLLoadError(event:IOErrorEvent) : void {
trace("XML load IOError: " + event.text);
this.xmlLoader.removeEventListener(Event.COMPLETE, this.onXMLLoaded);
this.xmlLoader.removeEventListener(IOErrorEvent.IO_ERROR, this.onXMLLoadError);
}
private function onXMLLoaded(event:Event) : void {
this.xmlLoader.removeEventListener(Event.COMPLETE, this.onXMLLoaded);
this.xmlLoader.removeEventListener(IOErrorEvent.IO_ERROR, this.onXMLLoadError);
this.resultsXML = XML(this.xmlLoader.data.toString());
this.loadRandomImage();
}
private function loadRandomImage() : void {
var max:int = this.resultsXML.FILE.length() - 1;
var rand:int = Math.ceil(Math.random() * (max - 0+1)) + 0 -1;
var imageFile:String = this.resultsXML.FILE[rand].@path;
this.imageLoader = new Loader();
this.imageLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, this.onImageLoadError);
this.imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, this.onImageLoaded);
try {
this.imageLoader.load(new URLRequest(imageFile));
}
catch (error:Error) {
trace("Error: " + error.message);
}
}
private function onImageLoadError(event:IOErrorEvent) : void {
trace("Image load IOError: " + event.text);
this.imageLoader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, this.onImageLoadError);
this.imageLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, this.onImageLoaded);
}
private function onImageLoaded(event:Event) : void {
this.imageLoader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, this.onImageLoadError);
this.imageLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, this.onImageLoaded);
this.image = new Sprite();
var bmp:Bitmap = this.imageLoader.content as Bitmap;
bmp.smoothing = true;
this.image.addChild(bmp);
this.addChild(this.image);
this.scaleAndCenterImage(this.image);
}
private function scaleAndCenterImage(img:Sprite) : void {
var landscape:Boolean = (img.width >= img.height);
var wider:Boolean = (img.width > this.stage.stageWidth);
var taller:Boolean = (img.height > this.stage.stageHeight);
// resize if needed
if (landscape && wider) {
// constrain size to width
img.width = this.stage.stageWidth;
img.height = (this.stage.stageWidth / img.width) * img.height;
}
else if (!landscape && taller) {
// constrain size to height
img.width = (this.stage.stageHeight / img.height) * img.width;
img.height = this.stage.stageHeight;
}
// center vertically and horizontally
img.y = Math.round(this.stage.stageHeight/2 - img.height/2);
img.x = Math.round(this.stage.stageWidth/2 - img.width/2);
}
}
}
Click here to see this basic sample in action
Click here to download a zip file containing the php script and as class
This is just one way to use the DomDocument class. For example, you could modify the php script to include other file types (swf, flv etc.) and do a range of things with them. I might post a more advanced script/example next but thought I’d get quick one up for now.
- Tweet this post (will automatically use the short url below)
- Short url for this post: http://bit.ly/OPyHz
Ben Kanizay
0 comment(s)
Track this comments via RSS 2.0 feed. Feel free to post the comment, or trackback from your web site.