PHP - 使用Simple XML复制XML节点

5

我需要使用Simple XML加载一个XML源,复制一个已存在的节点及其所有子节点,然后在渲染XML之前自定义此新节点的属性。有什么建议吗?

2个回答

23

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

2
+1 推荐使用 DOM。我在使用 SimpleXML 时遇到了很多问题。永远不要使用 SimpleXML,DOM 更强大,而且使用起来并不更难。 - Benbob
我必须注意到这一点,因为这非常重要。我不后悔花费半个小时用DOM重写我的脚本。现在它更加直观和易于维护。 - ivkremer

6

在使用SimpleXML时,我发现最好的方法是一种变通方法。它相当简单,但很有效:

// 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中似乎不存在的功能的解决方法,因此需要注意,如果您之前定义过任何对象引用,我预计这将破坏它们。


2
喜欢这个答案,非常简单且功能强大。 我必须稍微调整答案,因为'$newNode->asXML()'会写出XML标头,而不仅仅是原始的XML片段:$ domNode = dom_import_simplexml($ newNode);$xml = str_replace('<replaceMe/>',$ domNode->ownerDocument->saveXML($ domNode) ,$ xml->asXML()); - AaronP
1
你在 $newnode['attribute'] = $attValue; 中打错了字,应该是 $newNode['attribute'] = $attValue; - synkro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接