Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I change the name of an element in DOM?

Tags:

dom

php

xml

In PHP with DOM, I have a DomElement object which represents an <identity/> element.

I have one case where I need to change this so its element name is <person/>, but keep the same child elements and attributes.

What would be the simplest way of changing an element name of a DomElement and keeping its children and attributes?

Edit: I have just found a very similar question (though it doesn't have very good answers).

like image 343
thomasrutter Avatar asked Apr 22 '09 06:04

thomasrutter


People also ask

How do you change the name of an element?

Use the setAttribute() method to change the name attribute of an element, e.g. box. setAttribute('name', 'example-name') . The method sets or updates the value of an attribute on the specified element. Here is the HTML for the examples in this article.

How do I get the HTML element?

Users can use getElementById() method to access HTML element using the id. If any element doesn't exist with the passed id into the getElementById method, it returns the null value. Syntax: document.


2 Answers

Could you use importNode() to copy the childNodes of your <identity> element to a newly created <person> element?

function changeName($node, $name) {
    $newnode = $node->ownerDocument->createElement($name);
    foreach ($node->childNodes as $child){
        $child = $node->ownerDocument->importNode($child, true);
        $newnode->appendChild($child, true);
    }
    foreach ($node->attributes as $attrName => $attrNode) {
        $newnode->setAttribute($attrName, $attrNode);
    }
    $newnode->ownerDocument->replaceChild($newnode, $node);
    return $newnode;
}

$domElement = changeName($domElement, 'person');

Perhaps something like that would work, or you could try using cloneChild().

Edit: Actually, I just realized that the original function would lose the placement of the node. As per the question thomasrutter linked to, replaceChild() should be used.

like image 107
Calvin Avatar answered Oct 12 '22 12:10

Calvin


Thanks to your post, I could quickly solve the same issue for me. However, I had a DOM_NOT_FOUND exception. This is probably a PHP Version issue, since the original post is 5 years old.

According to the PHP Documentation (Feb 2014)

DOM_NOT_FOUND
  Raised if oldnode is not a child of this node. 

So, I have replaced

$newnode->ownerDocument->replaceChild($newnode, $node);

with

$node->parentNode->replaceChild($newnode, $node);

Here is the complete function (tested):

public static function changeTagName($node, $name) {
    $childnodes = array();
    foreach ($node->childNodes as $child){
        $childnodes[] = $child;
    }
    $newnode = $node->ownerDocument->createElement($name);
    foreach ($childnodes as $child){
        $child2 = $node->ownerDocument->importNode($child, true);
        $newnode->appendChild($child2);
    }
    foreach ($node->attributes as $attrName => $attrNode) {
        $attrName = $attrNode->nodeName;
        $attrValue = $attrNode->nodeValue;
        $newnode->setAttribute($attrName, $attrValue);
    }
    $node->parentNode->replaceChild($newnode, $node);
    return $newnode;
}

It is also worth mentioning that when you want to use this function, you should traverse the DOM Tree in reversed order as explained in other posts.

UPDATE: After months of using and updating to PHP Version 5.5.15 on windows, I had an error saying $attr could not be converted to a string. So I updated third for-each loop above.

like image 43
Kağan Kayal Avatar answered Oct 12 '22 11:10

Kağan Kayal