如何通过DOM对象在SimpleXML中重命名标记?

afu*_*ama 3 php dom simplexml

问题似乎很简单,但我无法访问SimpleXMLElement的标记名称.

假设我有以下XML结构:

<xml>
     <oldName>Stuff</oldName>
</xml>
Run Code Online (Sandbox Code Playgroud)

我希望它看起来像这样:

<xml>
     <newName>Stuff</newName>
</xml>
Run Code Online (Sandbox Code Playgroud)

这可能不做整个对象的副本吗?

我已经开始意识到我正在接近这个问题的方式的错误.似乎我需要将我的SimpleXMLElement转换为DOM对象.这样做后,我发现以我想要的方式操作对象非常困难(显然在DOM中重命名标签并不容易做到这一点).

所以...我能够通过导入将我的SimpleXMLElement导入到DOM对象中,但我发现很难进行克隆.

以下是克隆DOM对象背后的正确想法,还是我仍然离开:

$old = $dom->getElementsByTagName('old')->item(0); // The tag is unique in my case
$new = $dom->createElement('new');

/* ... some recursive logic to copy attributes and children of the $old node ... */

$old->ownerDocument->appendChild($new);
$new->ownerDocument->removeChild($old);
Run Code Online (Sandbox Code Playgroud)

Jos*_*vis 6

这可能是在不使用XSLT的情况下复制节点的子节点和属性的最简单方法:

function clonishNode(DOMNode $oldNode, $newName, $newNS = null)
{
    if (isset($newNS))
    {
        $newNode = $oldNode->ownerDocument->createElementNS($newNS, $newName);
    }
    else
    {
        $newNode = $oldNode->ownerDocument->createElement($newName);
    }

    foreach ($oldNode->attributes as $attr)
    {
        $newNode->appendChild($attr->cloneNode());
    }

    foreach ($oldNode->childNodes as $child)
    {
        $newNode->appendChild($child->cloneNode(true));
    }

    $oldNode->parentNode->replaceChild($newNode, $oldNode);
}
Run Code Online (Sandbox Code Playgroud)

你可以用这种方式:

$dom = new DOMDocument;
$dom->loadXML('<foo><bar x="1" y="2">x<baz/>y<quux/>z</bar></foo>');

$oldNode = $dom->getElementsByTagName('bar')->item(0);
clonishNode($oldNode, 'BXR');

// Same but with a new namespace
//clonishNode($oldNode, 'newns:BXR', 'http://newns');

die($dom->saveXML());
Run Code Online (Sandbox Code Playgroud)

它将使用具有新名称的克隆替换旧节点.

但请注意,这是原始节点内容的副本.如果您有任何指向旧节点的变量,它们现在无效.