PHP SimpleXML:在特定位置插入节点

时间:2010-07-29 09:28:42

标签: php xml simplexml

说我有XML:

<root>
  <nodeA />
  <nodeA />
  <nodeA />
  <nodeC />
  <nodeC />
  <nodeC />
</root>

如何在As和Cs之间插入“nodeB”?在PHP中,最好是通过SimpleXML?像:

<root>
  <nodeA />
  <nodeA />
  <nodeA />
  <nodeB />
  <nodeC />
  <nodeC />
  <nodeC />
</root>

2 个答案:

答案 0 :(得分:16)

以下是在其他SimpleXMLElement之后插入新的SimpleXMLElement的函数。由于SimpleXML无法直接实现这一点,因此它会在幕后使用一些DOM类/方法来完成工作。

function simplexml_insert_after(SimpleXMLElement $insert, SimpleXMLElement $target)
{
    $target_dom = dom_import_simplexml($target);
    $insert_dom = $target_dom->ownerDocument->importNode(dom_import_simplexml($insert), true);
    if ($target_dom->nextSibling) {
        return $target_dom->parentNode->insertBefore($insert_dom, $target_dom->nextSibling);
    } else {
        return $target_dom->parentNode->appendChild($insert_dom);
    }
}

以及如何使用它的例子(特定于你的问题):

$sxe = new SimpleXMLElement('<root><nodeA/><nodeA/><nodeA/><nodeC/><nodeC/><nodeC/></root>');
// New element to be inserted
$insert = new SimpleXMLElement("<nodeB/>");
// Get the last nodeA element
$target = current($sxe->xpath('//nodeA[last()]'));
// Insert the new element after the last nodeA
simplexml_insert_after($insert, $target);
// Peek at the new XML
echo $sxe->asXML();

如果您需要/需要解释 这是如何工作的(代码相当简单但可能包含外国概念),请问。

答案 1 :(得分:4)

Salathe的答案对我有帮助,但由于我使用了SimpleXMLElement的addChild方法,我寻求一种解决方案,让插入儿童作为第一个孩子更透明。解决方案是采用基于DOM的功能并将其隐藏在SimpleXMLElement的子类中:

class SimpleXMLElementEx extends SimpleXMLElement
{
    public function insertChildFirst($name, $value, $namespace)
    {
        // Convert ourselves to DOM.
        $targetDom = dom_import_simplexml($this);
        // Check for children
        $hasChildren = $targetDom->hasChildNodes();

        // Create the new childnode.
        $newNode = $this->addChild($name, $value, $namespace);

        // Put in the first position.
        if ($hasChildren)
        {
            $newNodeDom = $targetDom->ownerDocument->importNode(dom_import_simplexml($newNode), true);
            $targetDom->insertBefore($newNodeDom, $targetDom->firstChild);
        }

        // Return the new node.
        return $newNode;
    }
}

毕竟,SimpleXML允许指定要使用的元素类:

$xml = simplexml_load_file($inputFile, 'SimpleXMLElementEx');

现在,您可以在任何元素上调用insertChildFirst,以将新子项作为第一个子项插入。该方法将新元素作为SimpleXML元素返回,因此它的用法类似于addChild。当然,很容易创建一个insertChild方法,允许指定一个确切的元素来插入项目,但由于我现在不需要,我决定不这样做。