PHP - Дублировать XML-узел с использованием Simple XML

Мне нужно загрузить источник XML с помощью Simple XML, продублировать существующий узел со всеми его дочерними элементами, а затем настроить атрибут этого нового узла перед рендерингом XML. Любое предложение?


person cesko80    schedule 01.03.2010    source источник


Ответы (2)


SimpleXML не может этого сделать, поэтому вам придется использовать DOM. . Хорошая новость заключается в том, что DOM и SimpleXML — это две стороны одной медали, libxml. Таким образом, независимо от того, используете ли вы SimpleXML или DOM, вы работаете с одним и тем же деревом. Вот пример:

$thing = simplexml_load_string(
    '<thing>
        <node n="1"><child/></node>
    </thing>'
);

$dom_thing = dom_import_simplexml($thing);
$dom_node  = dom_import_simplexml($thing->node);
$dom_new   = $dom_thing->appendChild($dom_node->cloneNode(true));

$new_node  = simplexml_import_dom($dom_new);
$new_node['n'] = 2;

echo $thing->asXML();

Если вы часто делаете подобные вещи, вы можете попробовать SimpleDOM, который является расширение для SimpleXML, позволяющее использовать методы DOM напрямую, без преобразования из объектов DOM и в них.

include 'SimpleDOM.php';
$thing = simpledom_load_string(
    '<thing>
        <node n="1"><child/></node>
    </thing>'
);

$new = $thing->appendChild($thing->node->cloneNode(true));
$new['n'] = 2;

echo $thing->asXML();
person Josh Davis    schedule 01.03.2010
comment
+1 за рекомендацию DOM. Я столкнулся со многими проблемами с simpleXML. Никогда не используйте SimpleXML, DOM намного мощнее и не сложнее в использовании. - person Keyo; 15.09.2011
comment
Я должен заметить это еще и потому, что это так важно. Я не жалею, что потратил полчаса на то, чтобы переписать свой скрипт с помощью DOM. Теперь он намного более прямой и простой в обслуживании. - person ivkremer; 27.12.2013

С SimpleXML лучший способ, который я нашел, - это обходной путь. Это довольно bobo, но это работает:

// Strip it out so it's not passed by reference
$newNode = new SimpleXMLElement($xml->someNode->asXML());

// Modify your value
$newnode['attribute'] = $attValue;

// Create a dummy placeholder for it wherever you need it
$xml->addChild('replaceMe');

// Do a string replace on the empty fake node
$xml = str_replace('<replaceMe/>',$newNode->asXML(),$xml->asXML());

// Convert back to the object
$xml = new SimpleXMLElement($xml); # leave this out if you want the xml

Поскольку это обходной путь для функции, которой, похоже, нет в SimpleXML, вы должны знать, что я ожидаю, что это нарушит любые ссылки на объекты, которые вы определили до этого момента, если таковые имеются.

person Dan Crews    schedule 11.11.2011
comment
Мне нравится этот ответ, такой простой и отлично работает. Мне пришлось немного изменить ответ, так как '$newNode-›asXML()' записывала заголовок XML, а не только необработанный фрагмент XML: $domNode = dom_import_simplexml($newNode); $xml = str_replace('‹replaceMe/›',$domNode-›ownerDocument-›saveXML($domNode),$xml-›asXML()); - person AaronP; 09.05.2016