initializeDocument(); $destination = $this->visitChildren( $source->getDomDocument(), $destination ); return $this->createDocument( $destination ); } /** * Initialize destination document * * Initialize the structure which the destination document could be build * with. This may be an initial DOMDocument with some default elements, or * a string, or something else. * * @return mixed */ abstract protected function initializeDocument(); /** * Create document from structure * * Build a ezcDocumentDocument object from the structure created during the * visiting process. * * @param mixed $content * @return ezcDocumentDocument */ abstract protected function createDocument( $content ); /** * Recursively visit children of a document node. * * Recurse through the whole document tree and call the defined callbacks * for node transformations, defined in the class property * $visitorElementHandler. * * @param DOMNode $node * @param mixed $root * @return mixed */ public function visitChildren( DOMNode $node, $root ) { if ( $this->storage === null ) { $this->storage = new SplObjectStorage(); } // Recurse into child elements foreach ( $node->childNodes as $child ) { if ( $this->storage->contains( $child ) ) { $this->triggerError( E_WARNING, "Duplicate node processing '{$child->tagName}'." ); continue; } else { $this->storage->attach( $child ); } $root = $this->visitNode( $child, $root ); } return $root; } /** * Visit a single document node * * Visit a single document node and look up the correct visitor and us it * to handle the node. * * @param DOMNode $node * @param mixed $root * @return mixed */ public function visitNode( DOMNode $node, $root ) { switch ( $node->nodeType ) { case XML_ELEMENT_NODE: $root = $this->visitElement( $node, $root ); break; case XML_TEXT_NODE: $root = $this->visitText( $node, $root ); break; } return $root; } /** * Visit DOMElement nodes. * * @param DOMNode $node * @param mixed $root * @return void */ protected function visitElement( DOMElement $node, $root ) { if ( isset( $this->visitorElementHandler[$this->defaultNamespace][$node->tagName] ) ) { $root = $this->visitorElementHandler[$this->defaultNamespace][$node->tagName]->handle( $this, $node, $root ); } else { // Trigger notice for unhandled elements $this->triggerError( E_NOTICE, "Unhandled element '{$node->tagName}'." ); // Recurse into element nodes anyways $this->visitChildren( $node, $root ); } return $root; } /** * Visit text node. * * Visit a text node in the source document and transform it to the * destination result * * @param DOMText $text * @param mixed $root * @return mixed */ abstract protected function visitText( DOMText $text, $root ); /** * Set custom element handler * * Set handler for yet unhandled element or overwrite the handler of an * existing element. * * @param string $namespace * @param string $element * @param ezcDocumentElementVisitorHandler $handler * @return void */ public function setElementHandler( $namespace, $element, ezcDocumentElementVisitorHandler $handler ) { $this->visitorElementHandler[$namespace][$element] = $handler; } } ?>