Скопируйте потомки SimpleXMLElement в другой объект - PullRequest
0 голосов
/ 07 марта 2019

Учитывая два SimpleXMLElement объекта, структурированных следующим образом (идентично):

$ obj1

object SimpleXMLElement {
    ["@attributes"] =>
    array(0) {
    }
    ["event"] =>
    array(1) {
        [0] =>
        object(SimpleXMLElement) {
            ["@attributes"] =>
            array(1) {
                ["url"] =>
                string "example.com"
            }
        }
    }
}

$ obj2

object SimpleXMLElement {
    ["@attributes"] =>
    array(0) {
    }
    ["event"] =>
    array(1) {
        [0] =>
        object(SimpleXMLElement) {
            ["@attributes"] =>
            array(1) {
                ["url"] =>
                string "another-example.com"
            }
        }
    }
}

Я пытаюсь скопировать все дочерние элементы event из второго объекта в первый, как показано ниже:

foreach ($obj2->event as $event) {
    $obj1->event[] = $event
}

Они перемещаются, но скопированные объекты теперь пусты.

$ obj1

object SimpleXMLElement {
    ["@attributes"] =>
    array(0) {
    }
    ["event"] =>
    array(2) {
        [0] =>
        object(SimpleXMLElement) {
            ["@attributes"] =>
            array(1) {
                ["url"] =>
                string "example.com"
            }
        }
        [1] =>
        object(SimpleXMLElement) {
        }
    }
}

1 Ответ

1 голос
/ 10 марта 2019

Функциональность редактирования SimpleXML довольно ограничена, и в этом случае как выполняемое вами назначение, так и ->addChild могут устанавливать только текстовое содержимое нового элемента, а не его атрибуты и дочерние элементы.

Этоможет быть один случай, когда вам нужна мощь более сложного DOM API.К счастью, вы можете смешать их в PHP практически без штрафа, используя dom_import_simplexml и simplexml_import_dom, чтобы переключиться на другую оболочку.

Как только вы получитев представлении DOM вы можете использовать метод appendChild из DOMNode для добавления полного узла, но есть ловушка - вы можете добавлять только узлы, "принадлежащие" одному и тому же документу.Поэтому вам нужно сначала вызвать метод importNode в документе , который вы пытаетесь редактировать.

Собрав все это вместе, вы получите что-то вроде этого:

// Set up the objects you're copying from and to
// These don't need to be complete documents, they could be any element
$obj1 = simplexml_load_string('<foo><event url="example.com" /></foo>');
$obj2 = simplexml_load_string('<foo><event url="another.example.com" /></foo>');

// Get a DOM representation of the root element we want to add things to
// Note that $obj1_dom will always be a DOMElement not a DOMDocument, 
//   because SimpleXML has no "document" object
$obj1_dom = dom_import_simplexml($obj1);

// Loop over the SimpleXML version of the source elements
foreach ($obj2->event as $event) {
    // Get the DOM representation of the element we want to copy
    $event_dom = dom_import_simplexml($event);
    // Copy the element into the "owner document" of our target node
    $event_dom_copy = $obj1_dom->ownerDocument->importNode($event_dom, true);
    // Add the node as a new child
    $obj1_dom->appendChild($event_dom_adopted);
}

// Check that we have the right output, not trusting var_dump or print_r
// Note that we don't need to convert back to SimpleXML 
// - $obj1 and $obj1_dom refer to the same data internally
echo $obj1->asXML();
...