eval(art);

XSLT Transformations via mod_rewrite and PHP

by Philippe Hausler on Sep.23, 2007, under PHP, Web

Latently Apache does not have any methodology to transform XML via XSL templates. However there are a few features that can easily accomplish this feat. In most installations of Apache mod_rewrite is enabled by default. This allows any sent url to be dynamically behind the scenes redirected to another file. With some handy rules we can ensure that any XML file is first processed by a PHP script at a set location. Here is an example of an addition to a base website root .htaccess file.

RewriteEngine On
RewriteRule ^(.*\.xml)$ /xml.php [QSA]

This will redirect any file accessed that ends in a tag of .xml to our XML processing script but also send any query variables.When the XML processing script is executed, the script has basic parameters that are still attached to the original XML file being viewed. $_SERVER['REQUEST_URI']will still point to the original request: NOTE this is radically different than our uri of the script being redirected to. Of course we have both a path and a query parameter in this URI. The original file can then be represented as an expression $_SERVER['DOCUMENT_ROOT'].$url['path'].Once we have our XML file loaded, we need to determine what XSL stylesheets are included within the document.

$xml = new DOMDocument;
$xml->load($file);
$proc = new XSLTProcessor;
foreach($xml->childNodes
as $childNode){
   if(get_class($childNode)=="DOMProcessingInstruction"){
      if(strtolower($childNode->target) == "xml-stylesheet"){
         //match the type and href of the stylesheet
         preg_match("/type(?:\s*)=(?:\s*)\"(.*)\"/U",$childNode->data, $matches);
         $type = $matches[1];
         preg_match("/href(?:\s*)=(?:\s*)\"(.*)\"/U",$childNode->data, $matches);
         $href = $matches[1];
         //load the stylesheet into memory
         $xsl = new DOMDocument;
         $xsl->load(dirname($file)."/".$href); //<—- this is WRONG! but it works >.>
         $proc->importStyleSheet($xsl);
      }
   }
}

Since the variables passed to our XML “preprocessor” include some extra junk, we need to ensure that the passed variables are not haphazardly assigned (this limits this script to GET only)

parse_str($url['query'], $query);
foreach($query as $key=>$value){
   $proc->setParameter(,
$key, $value);
}

Next we need to apply our transform and then clean up.

$transformed = $proc->transformToDoc($xml);

Remove any, no longer needed, stylesheet references since the document is now fully formatted.

foreach($transformed->childNodes as $childNode){
   if(get_class($childNode)=="DOMProcessingInstruction"){
      if($childNode->target == "xml-stylesheet"){
         $transformed->removeChild($childNode);
      }
   }
}

After the clean-up, all we have left to do is actually output our newly stylized XML file. This same process could also apply to XHTML and also include modifications to the DOM tree.

header("Content-type: text/xml");
echo $transformed->saveXML();


Comments are closed.

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...