Mercurial > defr > templates
view class.template.php @ 14:54b0a41e5564
Menu un peu plus proche d'être fonctionnel.
Il y a de fortes chances qu'au final on obtienne un fonctionnement
se rapprochant de ça. Il faudrait toutefois pouvoir definir la
valeur de noeuds fils et pas d'attributs par contre a priori.
author | Franck Deroche <webmaster@defr.org> |
---|---|
date | Mon, 22 Oct 2007 10:07:42 +0200 |
parents | a7ce1a423cbe |
children | 51645aad97a8 |
line wrap: on
line source
<?php class Template { private $xmlDocument; private $xmlXPath; const NS = 'http://defr.net/2007/template'; function __construct($fileName, $shouldValidate = false) { $this->xmlDocument = new DOMDocument(); $this->xmlDocument->validateOnParse = $shouldValidate; $this->xmlDocument->preserveWhiteSpace = false; $this->xmlDocument->loadXML(file_get_contents($fileName)); $this->xmlXPath = new DOMXPath($this->xmlDocument); $this->xmlXPath->registerNamespace('_t', Template::NS); } function apply($selector, $obj, DOMElement $root = null) { if(!($root instanceof DOMElement)) $root = $this->xmlDocument->documentElement; $rootSelector = $this->parseSelector($selector, $root); if(is_array($obj)) $this->applyClone($rootSelector, $obj, $root); else { foreach($rootSelector->nodes as $node) { $content = $this->parseReplacement($obj); if(isset($rootSelector->attribute)) { $node->setAttribute($rootSelector->attribute, $obj); } else { if($node->namespaceURI == Template::NS) $this->replaceNode($node, $content); else $this->setNodeContent($node, $content); } } } } function applyClone($rootSelector, $obj, $root) { foreach($obj as $array) { $nodeName = key($array); foreach($rootSelector->nodes as $node) { $tmp = $this->getClonedNode($node, $nodeName); $futureNode = $tmp->clone; $futureNode = $node->insertBefore($futureNode, $tmp->orig); foreach($array as $sel => $test) { $locSelector = $this->parseSelector($sel, $node); if(isset($locSelector->attribute)) $futureNode->setAttribute($locSelector->attribute, $test); else { $content = $this->parseReplacement($test); $node->insertBefore($content, $tmp->orig); if($futureNode->namespaceURI == Template::NS) $this->replaceNode($futureNode, $content); else $this->setNodeContent($futureNode, $content); } } } } } function getClonedNode($node, $childNodeName) { $candidates = $this->parseSelector($childNodeName, $node)->nodes; foreach($candidates as $candidate) { if($candidate->getAttributeNS(Template::NS, 'toClone') == 'true') { $tmp = array(); $tmp['orig'] = $candidate; $cnode = $candidate->cloneNode(true); $cnode->removeAttributeNS(Template::NS, 'toClone'); $tmp['clone'] = $cnode; return (object)$tmp; } } } function parseSelector($selector, DOMElement $root) { $obj = array(); $pos = strpos($selector, '@'); if($pos !== false) { $obj['attribute'] = substr($selector,$pos +1); $selector = substr($selector, 0, $pos); } if($selector[0] == '#') { $obj['xpath'] = "//*[@_t:id='" . substr($selector, 1) . "']"; $obj['nodes'] = $this->xmlXPath->query($obj['xpath'], $root); } else { $obj['nodeName'] = $selector; $obj['nodes'] = $root->getElementsByTagName($selector); } return (object)$obj; } function parseReplacement($obj) { $retVal = NULL; if(is_string($obj)) $retVal = $this->xmlDocument->createTextNode($obj); else if($obj instanceof DOMDocument) $retVal = $obj->documentElement->clone(true); else if($obj instanceof DOMNode) $retVal = $obj->clone(true); else if($obj instanceof Template) { $node = $obj->xmlDocument->documentElement; $retVal = $this->xmlDocument->importNode($node, true); } return $retVal; } function setParams($array) { foreach($array as $selector => $obj) { $this->apply($selector, $obj); } } function replaceNode(DOMNode $node, DOMNode $content) { $parent = $node->parentNode; $parent->replaceChild($content, $node); } function setNodeContent(DOMElement $node, DOMNode $content) { // Suppress existing childs foreach($node->childNodes as $child) { $node->removeChild($child); } // Add the new child $node->appendChild($content); } function clean() { // Suppression des noeuds à cloner $nodes = $this->xmlXPath->query("//*[@_t:toClone]|//_t:*"); foreach($nodes as $node) { if($node->parentNode) { $node->parentNode->removeChild($node); } } } function __toString() { $this->clean(); $this->xmlDocument->formatOutput = true; return $this->xmlDocument->saveXML(); } }