<?php
/**------------------------------------------------------------------------------
* File: extendeddom.phplibrary
* Description: True DOMDocument and DOMElement abstraction
* Version: 1.0
* Author: Richard Keizer
* Email: ra dot keizer at gmail dot com
*------------------------------------------------------------------------------
* COPYRIGHT (c) 2011 Richard Keizer
*
* The source code included in this package is free software; you can
* redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation. This license can be
* read at:
*
* http://www.opensource.org/licenses/gpl-license.php
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*------------------------------------------------------------------------------
*
*
*/
class extDOMDocument extends DOMDocument {
public function __construct($version='1.0', $encoding=null) {
parent::__construct($version, $encoding);
$this->formatOutput = true;
}
public function createElement($classname, $name=null, $owner=null, $value=null) {
if (is_null($owner)) $owner = $this;
return (!is_null($name) && $this->getElementByName($name, $owner)) ? $this->getElementByName($name, $owner) : new $classname($owner, $name, $value);
}
public function createElementNS($namespaceURI, $classname, DOMNode $owner, $value=null) {
if (is_null($owner)) $owner = $this;
return $this->getElementByName($name, $owner) ? $this->getElementByName($name, $owner) : new $classname($owner, $name, $value, $namespaceURI);
}
public function getElementByName($name, $node=null) {
if (is_null($node)) $node = $this;
foreach($node->childNodes as $child) if ($child->hasAttribute('name') && $child->getAttribute('name') == $name) return $child;
}
public function marshal() {
return $this->saveXML();
}
public function unmarshal($xml) {
return $this->loadXML($xml);
}
public function loadXML($xml) {
$tmpdom = new DOMDocument('1.0');
$tmpdom->preserveWhiteSpace = false;
$tmpdom->loadXML($xml);
$stack = array($tmpdom, $this); //push source (=tmpdom's root) and target (=insertionpoint)
while (!empty($stack)) {
$source = array_shift($stack);
$target = array_shift($stack);
foreach($source->childNodes as $child) {
switch ($child->nodeType) {
case XML_ELEMENT_NODE: {
$new = $child->namespaceURI == '' ? $this->createElement($child->nodeName, $child->getAttribute('name'), $target) : $this->createElementNS($uri, $child->nodeName, $child->getAttribute('name'), $target);
foreach ($child->attributes as $attr) $new->setAttribute($attr->nodeName, $attr->nodeValue); //$new->appendChild($this->importNode($attr, true));
array_push($stack, $child);
array_push($stack, $new);
break;
}
case XML_TEXT_NODE: {
$target->appendChild($this->createTextNode($child->nodeValue)); //$target->nodeValue = $child->nodeValue;
break;
}
case XML_PI_NODE: {
$target->appendChild($this->createProcessingInstruction($child->nodeName, $child->nodeValue));
break;
}
case XML_COMMENT_NODE: {
//$target->appendChild($this->createComment($child->nodeValue));
break;
}
default: {
throw new Exception("nodeType '{$child->nodeType}' not implemented!");
}
}
}
}
}
}
//id is global unique
//name is local unique
class extDOMElement extends DOMElement {
private $this;
public function __construct($owner, $name=null, $value=null, $namespaceURI=null) {
parent::__construct(get_called_class(), $value, $namespaceURI);
$owner->appendChild($this); //append to owner
$this->setAttribute('id', uniqid('u')); //assign unique identifier
$this->setIdAttribute('id', true);
if ($name) $this->setAttribute('name', $name);
$this->this = $this; //IMPORTANT: if we don't store this extra reference the element would degrade to a DOMElement for some reason...
}
public function createElement($classname, $name=null, $value=null) {
return $this->ownerDocument->createElement($classname, $name, $this, $value);
}
public function getId() {
return $this->getAttribute('id');
}
public function getElementByName($name) {
return $this->ownerDocument->getElementByName($name, $this);
}
}
|