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

The*_*nen 10 php xml simplexml

说我有XML:

<root>
  <nodeA />
  <nodeA />
  <nodeA />
  <nodeC />
  <nodeC />
  <nodeC />
</root>
Run Code Online (Sandbox Code Playgroud)

如何在As和Cs之间插入"nodeB"?在PHP中,最好是通过SimpleXML?喜欢:

<root>
  <nodeA />
  <nodeA />
  <nodeA />
  <nodeB />
  <nodeC />
  <nodeC />
  <nodeC />
</root>
Run Code Online (Sandbox Code Playgroud)

sal*_*the 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

$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();
Run Code Online (Sandbox Code Playgroud)

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


Gol*_*rol 5

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

$xml = simplexml_load_file($inputFile, 'SimpleXMLElementEx');
Run Code Online (Sandbox Code Playgroud)

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