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

Php 在SimpleXML中,如何将现有SimpleXML元素添加为子元素?,php,oop,simplexml,Php,Oop,Simplexml,我有一个SimpleXMLElement对象$child和一个SimpleXMLElement对象$parent 如何将$child添加为$parent的子级?有没有办法在不转换为DOM的情况下实现这一点 addChild()方法似乎只允许我创建一个新的空元素,但当我要添加的元素$child也有子元素时,这并没有帮助。我想这里可能需要递归。我知道这不是最有用的答案,但特别是当您创建/修改XML时,我会转而使用DOM函数。SimpleXML很适合访问简单文档,但在更改文档方面却很差 如果Simpl

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

如何将$child添加为$parent的子级?有没有办法在不转换为DOM的情况下实现这一点


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

我知道这不是最有用的答案,但特别是当您创建/修改XML时,我会转而使用DOM函数。SimpleXML很适合访问简单文档,但在更改文档方面却很差


如果SimpleXML在所有其他地方都对您很友好,并且您希望继续使用它,那么您仍然可以选择暂时跳转到DOM函数来执行您需要的操作,然后使用and再次跳转回去。我不确定这是否有效,但它可能会帮助您解决问题。

我刚刚偶然发现这一页,并发现SimpleXML现在通过支持此功能

您也可以使用此方法添加任何级联元素:

$xml->addChild('parent');
$xml->parent->addChild('child');
$xml->parent->child->addChild('child_id','12345');
实际上,如果仔细研究如何定义
addChild()
,这是可能的(动态的)。我使用此技术使用递归和引用传递将任何数组转换为XML

  • addChild()
    返回所添加子元素的
    simplexmlement
  • 要添加叶节点,请使用
    $xml->addchild($nodeName,$nodeValue)
  • 要添加可能具有子节点或值的节点,请使用
    $xml->addChild($nodeName)
    ,没有值传递给
    addChild()
    。这 将导致具有SimpleXMLElement类型的子节点!不是 绳子
目标XML

<root>
    <node>xyz</node>
    <node>
        <node>aaa</node>
        <node>bbb</node>
    </node>
</root>

xyz
aaa
bbb
代码:

$root = new SimpleXMLElement('<root />');
//add child with name and string value.
$root.addChild('node', 'xyz'); 
//adds child with name as root of new SimpleXMLElement
$sub = $root->addChild('node');
$sub.addChild('node', 'aaa');
$sub.addChild('node', 'bbb');
$root=新的SimpleXMLElement(“”);
//添加具有名称和字符串值的子项。
$root.addChild('node','xyz');
//添加名为新SimpleXMLElement根的子级
$sub=$root->addChild('node');
$sub.addChild('node','aaa');
$sub.addChild('node','bbb');
不幸的是,它没有提供任何东西将两个元素结合在一起。因为,它更适合阅读而不是操纵。但是,姐妹扩展名
DOMDocument
用于编辑,您可以通过将两者合并在一起。以及它如何适用于特定的simplexmlements

下面显示了如何使用输入检查和其他一些选项。我举了两个例子。第一个示例是插入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);
}
此示例性函数允许在特定元素(包括根元素)之前附加XML或插入XML。在确定是否有需要添加的内容后,它使用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();
此示例性函数确实规范化了元素和属性列表,如Simplexml中的common。您可能希望将其更改为一次插入多个SimpleXmlElement,但正如下面的使用示例所示,我的示例不支持这一点(请参见属性示例):

//将元素本身附加到元素本身
simplexml\u import\u simplexml($parent,$parent);
//在第一个子元素()之前插入
simplexml\u import\u simplexml($parent->children(),$parent->test->this,true);
//向文档元素添加属性
$test=新的SimpleXMLElement(“”);
simplexml_import_simplexml($parent,$test->attributes());
echo$parent->asXML();
这是第一个使用示例的延续。因此,现在的输出是:

<?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>

现在
现在

我希望这是有帮助的。您可以和as/

幸运的是,现在时间还早,我不会浪费太多时间将整个内容转换为DOM(可能需要一个小时)。我认为这是我最终可能会得到的解决方案,除非其他人有一个非常惊人的想法。谢谢你的回答!我也遇到了同样的问题。切换到DOM,它会更好。这并不能回答问题。问题是如何添加已经是SimpleXMLElement的子级。这并不能回答问题,因为问题是如何添加已经是SimpleXMLElement节点的子级。非常好的解决方案。稍加调整,将其融入Laravel Trait,效果不错!!!非常感谢你
/**
 * 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);
}
// 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();
<?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>