Subversion Repositories PHPX

Rev

Blame | Last modification | View Log | RSS feed

1
<?php

namespace de\pointedears\dom;

class DOMDocument2 extends \DOMDocument
{
  /**
   * Renames an existing node of type <code>XML_ELEMENT_NODE</code>
   * or <code>XML_ATTRIBUTE_NODE</code>
   *
   * @param \DOMNode $node
   * @param string $namespaceURI = null
   * @param string $qualifiedName
   * @return \DOMNode The renamed node
   */

  public function renameNode (\DOMNode $node, $namespaceURI,
    $qualifiedName)
  {
    $result = false;

    if ($node->nodeType === XML_ELEMENT_NODE)
    {
      /*
       * Per W3C DOM Level 3 Core
       * <http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-renameNode>
       *
       * "If simply changing the name of the given node is not possible,
       * the following operations are performed:
       *
       * a new node is created, ...
       */

      $newNode = $this->createElementNS($namespaceURI,
        $qualifiedName, $node->nodeValue);

      /*
       * any registered event listener is registered on the new node
       * [skipped], any user data attached to the old node is removed
       * from that node the old node is removed from its parent if it
       * has one [done by replaceChild]
       */


      /* the children are moved to the new node */
      while (($childNode = $node->firstChild))
      {
        $newNode->appendChild($childNode);
      }

      /*
       * if the renamed node is an Element its attributes are moved
       * to the new node,
       */

      foreach ($node->attributes as $attribute)
      {
        $newNode->setAttributeNodeNS($attribute);
      }
      /*
       * the new node is inserted at the position the old node used
       * to have in its parent's child nodes list if it has one,
       * the user data that was attached to the old node is attached
       * to the new node."
       */

      $result = $node->parentNode->replaceChild($newNode, $node);
    }
    else if ($node->nodeType === XML_ATTRIBUTE_NODE)
    {
      /*
       * "When the node being renamed is an Attr that is attached
       * to an Element, the node is first removed from the Element
       * attributes map. Then, once renamed, either by modifying
       * the existing node or creating a new one as described above,
       * it is put back."
       */

      if (($ownerElement = $node->ownerElement))
      {
        $ownerElement->removeAttributeNS($node->namespaceURI, $node->name);

        $result = $ownerElement->setAttributeNS($namespaceURI, $qualifiedName, $node->value);

        if ($result !== false)
        {
          $newNode = $ownerElement->getAttributeNode($qualifiedName);
        }
      }
      else
      {
        /* Standalone attribute node */
        return new \DOMAttr($qualifiedName, $node->value);
      }
    }

    return ($result === false ? false : $newNode);
  }
}