SimpleXML: добавление одного дерева к другому

у меня есть два дерева XML и я хотел бы добавить одно дерево в качестве листа к другому.

видимо:

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

не работает, так как он копирует только первый корневой узел.

Хорошо, тогда я подумал, что пересеку все первое дерево, добавив каждый элемент один за другим ко второму.

но рассмотрим XML следующим образом:

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

как получить доступ к "ccc"? tree1->children() возвращает только "bbb"... .

4 ответов


вы не можете добавить "дерево" непосредственно с помощью SimpleXML, как вы видели. Однако вы можете использовать некоторые методы DOM для выполнения тяжелой работы, все еще работая над тем же базовым XML.

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

этот класс можно использовать для объектов SimpleXML, которые принимают дочерние объекты 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);
            }
        }
    }
}

Это хорошее решение из комментария PHP руководство страница (используя только SimpleXML, а не 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);
    }
} 

также есть образец использования.


очень милый Тео Heikonnen Небольшая настройка, чтобы заставить его работать так, как я хотел

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