20 Jul Skapa en XML som representerar filsystemet
Posted at 17:30h
in Uncategorized
I ett av våra projekt behövde vi skapa en XML utifrån filstruktur på en server.
Strukturen skulle visas med mappar först, i bokstavsordning, och sedan filer i bokstavsordning.
Skapandet av XML-filen var enkelt, men frågan var hur vi skulle sortera innehållet.
Det var dessutom önskvärt att kunna ändra sorteringsordningen i framtiden.
Lösningen var att stega igenom filsystemet och skapa en XML som sedan transformerades med en enkel XSL-mall. Genom att ändra XSL-mallen kan sorteringen ändras i efterhand utan att PHP-koden påverkas.
<?php header("Content-type: text/xml; charset=iso-8859-1"); $start_dir = '/YOUR SERVERS BASE PATH FOR STORING FILES/PATH/PATH'; $domtree = new DOMDocument('1.0', 'ISO-8859-1'); /* create the root element of the xml tree */ $xmlRoot = $domtree->createElement("rows"); $domAttribute = $domtree->createAttribute('parent'); //Create attribute $domAttribute->value = '0'; // Value for the created attribute $xmlRoot->appendChild($domAttribute); $xmlRoot = $domtree->appendChild($xmlRoot); //Append it to root element $folderElement; $folderName; $fileElement; $fileName; $parent; $rit = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $start_dir, FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::SELF_FIRST ); foreach ($rit as $path => $fileinfo) { $level = $rit->getDepth(); $parent = ($level==0) ? $xmlRoot : $folderElement; $exclude = "/MATCHING SUBSTRING FOR PATHS AND OR FILES TO EXCLUDE/"; $include = (strpos($path , $exclude)) === false ? true : false; if($include){ $counter++; $name = str_replace($start_dir, "", $path); $folderTitle = ($level==0) ? $name : substr($name, strrpos($name, '/') + 1); if ($fileinfo->isDir()) { $folderName = $name ."/"; $folderElement = $domtree->createElement("row"); $domAttribute = $domtree->createAttribute('id'); $domAttribute->value = $id; $folderElement->appendChild($domAttribute); $domAttribute = $domtree->createAttribute('isFolder'); $domAttribute->value = "1"; $folderElement->appendChild($domAttribute); $domAttribute = $domtree->createAttribute('fileName'); $domAttribute->value = $folderTitle; $folderElement->appendChild($domAttribute); $folderElement->appendChild($domAttribute); $domAttribute = $domtree->createAttribute('filePath'); $domAttribute->value = $name; $folderElement->appendChild($domAttribute); $cell = $domtree->createElement("cell", $folderTitle); $domAttribute = $domtree->createAttribute('image'); $domAttribute->value = "folder.gif"; $cell->appendChild($domAttribute); $folderElement->appendChild($cell); $folderElement->appendChild($domtree->createElement("cell","")); //XPath - find parent $xpath = new DomXpath($domtree); $parts = explode('/', $name); $lastPart = array_pop($parts); $parentFolderName = (count($parts)>=1) ? implode('/', $parts) : ''; $rowNode = $xpath->query('//row[@filePath="'. $parentFolderName .'"][1]')->item(0); $parent = ($rowNode instanceof DomElement) ? $rowNode : $xmlRoot; $folderElement = $parent->appendChild($folderElement); } else { $fileName = $folderTitle; $fileElement = $domtree->createElement("row"); $domAttribute = $domtree->createAttribute('id'); $domAttribute->value = $id; $fileElement->appendChild($domAttribute); $domAttribute = $domtree->createAttribute('isFolder'); $domAttribute->value = "2"; $fileElement->appendChild($domAttribute); $domAttribute = $domtree->createAttribute('filePath'); $domAttribute->value = $fileName; $fileElement->appendChild($domAttribute); $cell = $domtree->createElement("cell", $fileName); $domAttribute = $domtree->createAttribute('image'); $domAttribute->value = "file.gif"; $fileElement->appendChild($cell); $fileElement->appendChild($domtree->createElement("cell","<input type='checkbox' class='selectFile' name='". $fileName ."-". $id ."'>")); //XPath - find parent $xpath = new DomXpath($domtree); $parts = explode('/', $name); $lastPart = array_pop($parts); $parentFolderName = (count($parts)>=1) ? implode('/', $parts) : ''; $rowNode = $xpath->query('//row[@filePath="'. $parentFolderName .'"][1]')->item(0); $parent = ($rowNode instanceof DomElement) ? $rowNode : $xmlRoot; $fileElement = $parent->appendChild($fileElement); } } } $xml = $domtree->saveXML(); $xsl = new DOMDocument; $xsl->load('fileRun-sort.xsl'); $proc = new XSLTProcessor(); $proc->importStyleSheet($xsl); $sortedXml = $proc->transformToXML($domtree); echo $sortedXml; ?>
XSLT
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="1.0"> <xsl:output encoding="ISO-8859-1" method="xml"/> <xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="node() | @*"/> </xsl:copy> </xsl:template> <!-- Sort elements rows / row First sort by attribute isFolder then sort on attribute fileName (path) --> <xsl:template match="rows | row"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:apply-templates select="*"> <xsl:sort select="@isFolder" data-type="text" order="ascending"/> <xsl:sort select="@fileName" data-type="text" order="ascending"/> </xsl:apply-templates> </xsl:copy> </xsl:template> <!-- Remove attributes used for sorting --> <xsl:template match="row/@isFolder" /> <xsl:template match="row/@filePath" /> </xsl:stylesheet>