在SimpleXML中,如何将现有的SimpleXMLElement添加为子元素?

tho*_*ter 6 php oop simplexml

我有一个SimpleXMLElement对象$ child和一个SimpleXMLElement对象$ parent.

如何将$ child添加为$ parent的子级?有没有办法在不转换为DOM的情况下执行此操作?

addChild()方法似乎只允许我创建一个新的空元素,但是当我想添加$ child的元素也有子元素时,这没有用.我想我可能需要递归.

hak*_*kre 8

不幸的是SimpleXMLElement,没有提供任何将两个元素结合在一起 正如@nickf写的那样,它更适合阅读而非操纵.但是,姐妹扩展DOMDocument程序用于编辑,您可以将两者一起通过dom_import_simplexml().而@salathe显示了相关的答案是如何工作的具体SimpleXMLElements.

以下显示了如何使用输入检查和更多选项.我用两个例子来做.第一个示例是插入XML字符串的函数:

/**
 * Insert XML into a SimpleXMLElement
 *
 * @param SimpleXMLElement $parent
 * @param string $xml
 * @param bool $before
 * @return bool XML string added
 */
function simplexml_import_xml(SimpleXMLElement $parent, $xml, $before = false)
{
    $xml = (string)$xml;

    // check if there is something to add
    if ($nodata = !strlen($xml) or $parent[0] == NULL) {
        return $nodata;
    }

    // add the XML
    $node     = dom_import_simplexml($parent);
    $fragment = $node->ownerDocument->createDocumentFragment();
    $fragment->appendXML($xml);

    if ($before) {
        return (bool)$node->parentNode->insertBefore($fragment, $node);
    }

    return (bool)$node->appendChild($fragment);
}
Run Code Online (Sandbox Code Playgroud)

该示例性函数允许附加XML或将其插入特定元素(包括根元素)之前.在发现是否有要添加的内容之后,它使用DOMDocument 函数和方法将XML作为文档片段插入,如何在PHP DOMDocument中导入XML字符串中也概述了它.用法示例:

$parent = new SimpleXMLElement('<parent/>');

// insert some XML
simplexml_import_xml($parent, "\n  <test><this>now</this></test>\n");

// insert some XML before a certain element, here the first <test> element
// that was just added
simplexml_import_xml($parent->test, "<!-- leave a comment -->\n  ", $before = true);

// you can place comments above the root element
simplexml_import_xml($parent, "<!-- this works, too -->", $before = true);

// but take care, you can produce invalid XML, too:
// simplexml_add_xml($parent, "<warn><but>take care!</but> you can produce invalid XML, too</warn>", $before = true);

echo $parent->asXML();
Run Code Online (Sandbox Code Playgroud)

这给出了以下输出:

<?xml version="1.0"?>
<!-- this works, too -->
<parent>
  <!-- leave a comment -->
  <test><this>now</this></test>
</parent>
Run Code Online (Sandbox Code Playgroud)

第二个例子是插入一个SimpleXMLElement.如果需要,它会使用第一个功能.它基本上检查是否有任何事情要做,以及要导入哪种元素.如果它是一个属性,它只会添加它,如果它是一个元素,它将被序列化为XML,然后作为XML添加到父元素:

/**
 * Insert SimpleXMLElement into SimpleXMLElement
 *
 * @param SimpleXMLElement $parent
 * @param SimpleXMLElement $child
 * @param bool $before
 * @return bool SimpleXMLElement added
 */
function simplexml_import_simplexml(SimpleXMLElement $parent, SimpleXMLElement $child, $before = false)
{
    // check if there is something to add
    if ($child[0] == NULL) {
        return true;
    }

    // if it is a list of SimpleXMLElements default to the first one
    $child = $child[0];

    // insert attribute
    if ($child->xpath('.') != array($child)) {
        $parent[$child->getName()] = (string)$child;
        return true;
    }

    $xml = $child->asXML();

    // remove the XML declaration on document elements
    if ($child->xpath('/*') == array($child)) {
        $pos = strpos($xml, "\n");
        $xml = substr($xml, $pos + 1);
    }

    return simplexml_import_xml($parent, $xml, $before);
}
Run Code Online (Sandbox Code Playgroud)

此示例性函数确实标准化了Simplexml中常见的元素和属性列表.您可能希望将其更改为一次插入多个SimpleXMLElements,但正如下面的用法示例所示,我的示例不支持它(请参阅属性示例):

// append the element itself to itself
simplexml_import_simplexml($parent, $parent);

// insert <this> before the first child element (<test>)
simplexml_import_simplexml($parent->children(), $parent->test->this, true);

// add an attribute to the document element
$test = new SimpleXMLElement('<test attribute="value" />');
simplexml_import_simplexml($parent, $test->attributes());

echo $parent->asXML();
Run Code Online (Sandbox Code Playgroud)

这是第一个用法示例的延续.因此现在的输出是:

<?xml version="1.0"?>
<!-- this works, too -->
<parent attribute="value">
  <!-- leave a comment -->
  <this>now</this><test><this>now</this></test>
<!-- this works, too -->
<parent>
  <!-- leave a comment -->
  <test><this>now</this></test>
</parent>
</parent>
Run Code Online (Sandbox Code Playgroud)

我希望这是有帮助的.你可以找到一个要点代码在线演示/PHP版本的概述.


nic*_*ckf 6

我知道这不是最有用的答案,但特别是因为你正在创建/修改XML,我将切换到使用DOM函数.SimpleXML适用于访问简单文档,但在更改它们方面却很差.

如果SimpleXML在所有其他地方善待您,并且您想坚持使用它,您仍然可以选择暂时跳转到DOM功能以执行您需要的操作,然后再使用dom_import_simplexml()和跳回去simplexml_import_dom().我不确定这是多么有效,但它可能会帮助你.