2010-08-05 4 views
10

J'ai deux arbres XML et j'aimerais ajouter un arbre comme feuille à l'autre.SimpleXML: ajouter un arbre à un autre

Apparemment:

$tree2->addChild('leaf', $tree1); 

ne fonctionne pas, comme il ne copie que le premier nœud racine. Ok, alors j'ai pensé que je traverserais tout le premier arbre, en ajoutant chaque élément un par un au second.

Mais considérez XML comme ceci:

<root> 
    aaa 
    <bbb/> 
    ccc 
</root> 

Comment accéder à "ccc"? tree1->children() renvoie simplement "bbb" ....

Répondre

25

Vous ne pouvez pas ajouter un "arbre" directement en utilisant SimpleXML, comme vous l'avez vu. Cependant, vous pouvez utiliser certaines méthodes DOM pour effectuer le gros du travail tout en travaillant sur le même XML sous-jacent.

$xmldict = new SimpleXMLElement('<dictionary><a/><b/><c/></dictionary>'); 
$kitty = new SimpleXMLElement('<cat><sound>meow</sound><texture>fuzzy</texture></cat>'); 

// Create new DOMElements from the two SimpleXMLElements 
$domdict = dom_import_simplexml($xmldict->c); 
$domcat = dom_import_simplexml($kitty); 

// Import the <cat> into the dictionary document 
$domcat = $domdict->ownerDocument->importNode($domcat, TRUE); 

// Append the <cat> to <c> in the dictionary 
$domdict->appendChild($domcat); 

// We can still use SimpleXML! (meow) 
echo $xmldict->c->cat->sound; 
+0

Est-ce que excatly ce que je veux, merci beaucoup! –

+0

Lorsque je fais cela, les espaces de noms sur le noeud que j'importe sont éjectés. Comment puis-je empêcher cela? –

0

Très belle Theo Heikonnen peaufinage légère pour faire fonctionner la façon dont je voulais

 
    function addsubtree(&$xml1,&$xml2) 
    {// Create new DOMElements from the two SimpleXMLElements 
     $dom1 = dom_import_simplexml($xml1); 
     $dom2 = dom_import_simplexml($xml2); 
     // Import the into the document 
     $dom2 = $dom1->ownerDocument->importNode($dom2, TRUE); 
     // Append the to 
     $dom1->appendChild($dom2); 
    } 

    $xml1 = new SimpleXMLElement('<xml/>'); 
    $xml2 = new SimpleXMLElement('<sub/>'); 

    $xml2->addChild('test','data'); 
    $temp=$xml1->addChild('sub1'); 

    header('Content-type: text/xml'); 
    header('Pragma: public'); 
    header('Cache-control: private'); 
    header('Expires: -1'); 
    addsubtree($temp,$xml2); 

    // We can still use SimpleXML! (meow) 
    echo $xml1->asXML(); 
8

C'est une solution agréable de commentaires sur PHP manual page (en utilisant uniquement SimpleXML, non DOM):

function append_simplexml(&$simplexml_to, &$simplexml_from) 
{ 
    foreach ($simplexml_from->children() as $simplexml_child) 
    { 
     $simplexml_temp = $simplexml_to->addChild($simplexml_child->getName(), (string) $simplexml_child); 
     foreach ($simplexml_child->attributes() as $attr_key => $attr_value) 
     { 
      $simplexml_temp->addAttribute($attr_key, $attr_value); 
     } 

     append_simplexml($simplexml_temp, $simplexml_child); 
    } 
} 

Il existe également un exemple d'utilisation.

+1

C'était simple utile. Pour mes données, j'avais besoin d'enrouler le second paramètre de addChild dans htmlspecialchars() –

10

Vous pouvez utiliser cette classe pour SimpleXML objets qui acceptent les enfants append

<?php 

class MySimpleXMLElement extends SimpleXMLElement 
{ 
    /** 
    * Add SimpleXMLElement code into a SimpleXMLElement 
    * 
    * @param MySimpleXMLElement $append 
    */ 
    public function appendXML($append) 
    { 
     if ($append) { 
      if (strlen(trim((string)$append)) == 0) { 
       $xml = $this->addChild($append->getName()); 
      } else { 
       $xml = $this->addChild($append->getName(), (string)$append); 
      } 

      foreach ($append->children() as $child) { 
       $xml->appendXML($child); 
      } 

      foreach ($append->attributes() as $n => $v) { 
       $xml->addAttribute($n, $v); 
      } 
     } 
    } 
}