How do you rename a tag in SimpleXML through a DOM object?

后端 未结 4 430
隐瞒了意图╮
隐瞒了意图╮ 2020-12-02 00:51

The problem seems straightforward, but I\'m having trouble getting access to the tag name of a SimpleXMLElement.

Let\'s say I have the follow XML structure:

相关标签:
4条回答
  • 2020-12-02 01:27

    Maybe easier way would be to replace the tags using preg functions for the XML source string?

    Cleaner way

    Create XSLT XML transformation file and use xsl PHP extension to translate it.

    For this see this answer – Rename nodes with XSLT. PHP code part could be found in PHP documentation.

    0 讨论(0)
  • 2020-12-02 01:30

    Rather late but I came up with the fallowing solution by replacing the hell out of the xml. I thought this might help some people as I couldnt find any good solution on the web without copying all children.

    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);
    }
    

    Sidenote: This function can be simplified but I quickly rewrote this function in order to post this here. The original function I use looks a little bit different

    0 讨论(0)
  • 2020-12-02 01:40

    Is this possible to do without doing a copy of the entire object?

    Nope, it's not.

    You could do it in XSLT via an "identity transform". If you search around for "rename tag" and "identity transform" you should find a few examples, assuming XSLT is an option.

    0 讨论(0)
  • 2020-12-02 01:51

    Here's what's probably the simplest way to copy a node's children and attributes without using 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);
    }
    

    Which you can use this way:

    $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());
    

    It will replace the old node with a clone with a new name.

    Attention though, this is a copy of the original node's content. If you had any variable pointing to the old nodes, they are now invalid.

    0 讨论(0)
提交回复
热议问题