Подтвердить что ты не робот

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

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

По-видимому:

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

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

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

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

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

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

4b9b3361

Ответ 1

Вы не можете добавить "дерево" напрямую, используя 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;

Ответ 2

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

Ответ 3

Это хорошее решение из комментария Страница руководства 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);
    }
} 

Здесь также есть пример использования.

Ответ 4

Очень хороший Тео Хейконн Небольшая настройка, чтобы она работала так, как я хотел.

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