| 
<?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);
 }
 }
 
 
 |