2010-08-07 47 views
2

当我添加一个子节点时,如何根据它的同名来选择它的位置?使用带索引位置的addChild

下面是一个例子:

<?php 
    $_XML = ' <Test> 
        <Menu> 
         <Link href="page1.htm" /> 
         <Link href="page2.htm" /> 
         <Link href="page4.htm" /> 
        </Menu> 
       </Test>'; 

    $_RenderedXML = new SimpleXMLElement($_XML); 

    //Add a new Link node 
    $_NewLink = $_RenderedXML->Menu->addChild("Link"); 
    $_NewLink->addAttribute("href", "page3.htm"); 

    echo $_RenderedXML->asXML(); 
?> 

,这会使得新节点的XML低于它的sibbling。 我想指定它的位置。

addChild("Link", 2) //or something. 

回答

2

我知道Artefacto's answer已被接受,但它看起来是做的比需要更多的工作。一个更简单的替代方案,使用他的函数签名,可能看起来像下面的函数。

function addchild_at(SimpleXMLElement $sxml, $tagname, $i) 
{ 
    $parent = dom_import_simplexml($sxml); 
    $child = $parent->ownerDocument->createElement($tagname); 
    $target = $parent->getElementsByTagname('*')->item($i); 
    if ($target === NULL) { 
     $parent->appendChild($child); 
    } else { 
     $parent->insertBefore($child, $target); 
    } 
} 
+0

不错,我不知道你可以用'getElementsByTagname('*')'检索所有元素。 – Artefacto 2010-08-09 11:43:24

+0

@艺术,现在你做。 :-) – salathe 2010-08-09 11:46:52

1

你必须退回到DOM和使用dom_import_simplexml

$_RenderedXML = new SimpleXMLElement($_XML); 

//Add a new Link node 
addchild_at($_RenderedXML->Menu, "Link", 2); 
$_RenderedXML->Menu->Link[2]->addAttribute("href", "page3.htm"); 


function addchild_at(SimpleXMLElement $sxml, $tagname, $i) { 
    $elem = dom_import_simplexml($sxml); 
    $new = $elem->ownerDocument->createElement($tagname); 
    $chnodes = array(); 
    foreach ($elem->childNodes as $cn) { 
     $chnodes[] = $cn; 
    } 
    $chnodes = array_filter($chnodes, 
     function (DOMNode $dn) { return $dn->nodeType == XML_ELEMENT_NODE; } 
    ); 
    $chnodes = array_values($chnodes); 

    if ($i < count($chnodes)) 
     $elem->insertBefore($new, $chnodes[$i]); 
    else 
     $elem->appendChild($new); 
} 
+0

太棒了!它按预期工作。 – Cybrix 2010-08-08 00:00:44