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

Php 如何通过DOM对象重命名SimpleXML中的标记?,php,dom,simplexml,Php,Dom,Simplexml,问题似乎很简单,但我在访问SimpleXMLElement的标记名时遇到了问题 假设我有以下XML结构: <xml> <oldName>Stuff</oldName> </xml> 也许更简单的方法是使用preg函数替换XML源字符串的标记 清洁方式 创建XSLT XML转换文件并使用xsl PHP扩展名对其进行翻译 对此,请参见此答案。 PHP代码部分可以在PHP文档中找到 这是否可以在不复制整个对象的情况下执行 不,不是 您可以通过

问题似乎很简单,但我在访问SimpleXMLElement的标记名时遇到了问题

假设我有以下XML结构:

<xml>
     <oldName>Stuff</oldName>
</xml>

也许更简单的方法是使用preg函数替换XML源字符串的标记

清洁方式

创建XSLT XML转换文件并使用xsl PHP扩展名对其进行翻译

对此,请参见此答案。 PHP代码部分可以在PHP文档中找到

这是否可以在不复制整个对象的情况下执行

不,不是


您可以通过“身份转换”在XSLT中实现这一点。如果您搜索“重命名标记”和“标识转换”,您应该会找到一些示例,假设XSLT是一个选项。

以下是不使用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);
}
您可以通过以下方式使用:

$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());
$dom=新的DOMDocument;
$dom->loadXML('xyz');
$oldNode=$dom->getElementsByTagName('bar')->项(0);
clonishNode($oldNode,'BXR');
//相同,但具有新名称空间
//clonishNode($oldNode,'newns:BXR','http://newns');
die($dom->saveXML());
它将用新名称的克隆替换旧节点


请注意,这是原始节点内容的副本。如果有任何变量指向旧的节点,那么它们现在就无效了。

虽然已经很晚了,但我还是通过替换xml找到了休闲解决方案。我想这可能会帮助一些人,因为如果不复制所有的孩子,我在网上找不到任何好的解决方案

function RenameNode(SimpleXMLElement $Entire_XML, SimpleXMLElement $Node, $New_Title) 
{    
    $Full_XML   = $Entire_XML->asXML();
    $Old_Title  = $Node->getName();
    $XML_String = $Node->asXML();
    $Replaced   = preg_replace("/$Old_Title/", $New_Title, $XML_String, 1);

    if (count($Node->children())>0) 
    {
        $Replaced = strrev(
            preg_replace(
                strrev("/$Old_Title/"), 
                strrev($New_Title), 
                strrev($Replaced), 
                1
            )
        );    
    }

    $Full_XML = str_replace($XML_String, $Replaced, $Full_XML);

    return simplexml_load_string($Full_XML);
}

旁注:这个函数可以简化,但我很快重写了这个函数,以便在这里发布。我使用的原始函数看起来有点不同

请显示您尝试过的代码。可能,但必须有一个更干净的方法。请在答案中查看更干净的方法。我没有以这种方式使用变量,因此这是完美的!谢谢此解决方案的问题在于,它将替换文本,无论是完整或部分标记名、文本还是其他形式。要使用XML,正则表达式需要确保只重命名预期的XML的元素。有了这一点,这可能是概念上更简单的方法。
$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());
function RenameNode(SimpleXMLElement $Entire_XML, SimpleXMLElement $Node, $New_Title) 
{    
    $Full_XML   = $Entire_XML->asXML();
    $Old_Title  = $Node->getName();
    $XML_String = $Node->asXML();
    $Replaced   = preg_replace("/$Old_Title/", $New_Title, $XML_String, 1);

    if (count($Node->children())>0) 
    {
        $Replaced = strrev(
            preg_replace(
                strrev("/$Old_Title/"), 
                strrev($New_Title), 
                strrev($Replaced), 
                1
            )
        );    
    }

    $Full_XML = str_replace($XML_String, $Replaced, $Full_XML);

    return simplexml_load_string($Full_XML);
}