SimpleXML, как добавить дочерний элемент в узел?

Когда я звоню

addChild('actor', 'John Doe');

этот ребенок добавляется последним. Есть ли способ сделать этого нового ребенка первым ребенком?


person understack    schedule 19.01.2010    source источник


Ответы (3)


Как уже упоминалось, SimpleXML не поддерживает это, поэтому вам придется использовать DOM. Вот что я рекомендую: расширяйте SimpleXMLElement тем, что вам нужно использовать в своих программах. Таким образом, вы можете оставить все манипуляции с DOM и другую магию XML вне вашей реальной программы. Разделяя эти два вопроса, вы повышаете удобочитаемость и удобство сопровождения.

Вот как расширить SimpleXMLElement с помощью нового метода prependChild():

class my_node extends SimpleXMLElement
{
    public function prependChild($name, $value)
    {
        $dom = dom_import_simplexml($this);

        $new = $dom->insertBefore(
            $dom->ownerDocument->createElement($name, $value),
            $dom->firstChild
        );

        return simplexml_import_dom($new, get_class($this));
    }
}

$actors = simplexml_load_string(
    '<actors>
        <actor>Al Pacino</actor>
        <actor>Zsa Zsa Gabor</actor>
    </actors>',
    'my_node'
);

$actors->addChild('actor', 'John Doe - last');
$actors->prependChild('actor', 'John Doe - first');

die($actors->asXML());
person Josh Davis    schedule 19.01.2010
comment
Вызов неопределенного метода SimpleXMLElement::prependChild() - person user254153; 15.12.2016

Не похоже, что SimpleXML поддерживает это, поэтому у вас есть два варианта:

  1. Вместо этого используйте модуль DOM (или, возможно, один из других модулей XML) и используйте метод DOMNode::insertBefore или

  2. Создайте новый SimpleXMLElement, скопируйте атрибуты, затем добавьте новый узел, после этого добавьте все дочерние элементы исходного узла, а затем замените оригинал новым.

обновление: еще немного просмотрев документы, я бы предложил что-то вроде следующего (при условии, что вы по-прежнему хотите по большей части придерживаться SimpleXML, в противном случае просто используйте DOM напрямую для всего):

$dom_elem = dom_import_simplexml($simple_xml_element);
$dom_elem->insertBefore(dom_import_simplexml($new_element), $dom_elem->firstChild);
person pib    schedule 19.01.2010
comment
Я уже использую 2-й подход. Но это выглядело некрасиво, поэтому я подумал о том, чтобы попросить лучшие альтернативы. - person understack; 19.01.2010

Предполагая, что вы можете использовать функцию insert_before, вы можете использовать следующую функцию:

function prependChild (parent, node) { parent.insertBefore (node, parent.firstChild); }

Ссылка на источник: XML Matters: Beyond DOM

person rs987    schedule 19.01.2010