SimpleXMLElement :: addChild()不起作用

时间:2016-06-20 08:11:48

标签: php

在我的PHP代码中,我有两个变量$parent$child。它们都有一些xml数据。在$parent变量中,有一个名为<payheads>的标记,其中可能包含多个<payhead>标记。在$child变量中,只有一个<payhead>标记。我想要的是,我想在<payheads>变量的$parent标记的末尾添加该子项。我的代码如下:

<?php

$parent = new SimpleXMLElement('<review_sr><status>Review Complete</status><payheads><payhead><code>ABAS</code><old_value>0.00</old_value><new_value>63570.00</new_value><review_id>1234567890</review_id><review_time>20160614:11:00:47</review_time><status>Accepted</status></payhead></payheads><current_gross_allowance>50481.00</current_gross_allowance><review_gross_allowance>114051.00</review_gross_allowance></review_sr>');

$child = new SimpleXMLElement('<source><payhead><code>DMG</code><old_value>500.00</old_value><new_value>0.00</new_value><review_id>1234567890</review_id><review_time>20160620:12:41:17</review_time><status>Accepted</status></payhead></source>');
$child = $child->xpath('//payhead'); //This is to ignore the xml declaration that is automatically produced by the SimpleXMLElement constructor
$child = $child[0];                 //I've tried LIBXML_NOXMLDECL  but its not working, that's why these two lines.

//var_dump($parent);
//var_dump($child->asXML());

$parentNode = $parent->xpath('//payheads');
$parentNode[0]->addChild('payhead', $child);
//var_dump($parentNode[0]);
foreach($parent as $key=>$value)
    foreach($value as $key=>$value)
        var_dump($value); //only 1 payhead is shown. but there should be 2 of them.

?>  

实际输出:

object(SimpleXMLElement)[5]
  public 'code' => string 'ABAS' (length=4)
  public 'old_value' => string '0.00' (length=4)
  public 'new_value' => string '63570.00' (length=8)
  public 'review_id' => string '1234567890' (length=10)
  public 'review_time' => string '20160614:11:00:47' (length=17)
  public 'status' => string 'Accepted' (length=8)

object(SimpleXMLElement)[6]

预期产出:

object(SimpleXMLElement)[5]
  public 'code' => string 'ABAS' (length=4)
  public 'old_value' => string '0.00' (length=4)
  public 'new_value' => string '63570.00' (length=8)
  public 'review_id' => string '1234567890' (length=10)
  public 'review_time' => string '20160614:11:00:47' (length=17)
  public 'status' => string 'Accepted' (length=8)

object(SimpleXMLElement)[6]  
  public 'code' => string 'DMG' (length=4)
  public 'old_value' => string '500.00' (length=4)
  public 'new_value' => string '0.00' (length=8)
  public 'review_id' => string '1234567890' (length=10)
  public 'review_time' => string '20160620:12:41:17' (length=17)
  public 'status' => string 'Accepted' (length=8)

我做错了什么?

2 个答案:

答案 0 :(得分:2)

addChild接受 string 参数 - 第一个是要创建的标记名称,(可选)第二个是其文本内容,而(可选)第三个是元素的命名空间

你不能只是传递另一个要使用的元素。事实上SimpleXMLElement似乎对于这种操作来说太简单了。

相反,请考虑使用DOMDocument,如下所示:

<?php
$parent = new DOMDocument();
$parent->loadXML('<review_sr><status>Review Complete</status><payheads><payhead><code>ABAS</code><old_value>0.00</old_value><new_value>63570.00</new_value><review_id>1234567890</review_id><review_time>20160614:11:00:47</review_time><status>Accepted</status></payhead></payheads><current_gross_allowance>50481.00</current_gross_allowance><review_gross_allowance>114051.00</review_gross_allowance></review_sr>');

$child = new DOMDocument();
$child->loadXML('<source><payhead><code>DMG</code><old_value>500.00</old_value><new_value>0.00</new_value><review_id>1234567890</review_id><review_time>20160620:12:41:17</review_time><status>Accepted</status></payhead></source>');
$childNode = $child->getElementsByTagName('payhead')->item(0);

$parentNode = $parent->getElementsByTagName('payheads')->item(0);
$parentNode->appendChild($child);
foreach($parent->getElementsByTagName('payhead') as $payhead) {
    var_dump($payhead);
}

如果需要,您可以使用这些支付头并将其传递给SimpleXMLElement以便以非常简单的方式获取其属性:

$simplePayhead = simplexml_import_dom($payhead);
var_dump($simplePayhead);

答案 1 :(得分:1)

请试试这个。问题是simplexmlelement的addChild()需要一个字符串,并且您正在尝试将其类型转换的对象附加到null。

  

public SimpleXMLElement SimpleXMLElement :: addChild(string $ name [,string $ value [,string $ namespace]])

您需要使用DOM和appendChild代替DOM。

function sxml_append(SimpleXMLElement $to, SimpleXMLElement $from) {
    $toDom = dom_import_simplexml($to);
    $fromDom = dom_import_simplexml($from);
    $toDom->appendChild($toDom->ownerDocument->importNode($fromDom, true));
}

$parent = new SimpleXMLElement('<review_sr><status>Review Complete</status><payheads><payhead><code>ABAS</code><old_value>0.00</old_value><new_value>63570.00</new_value><review_id>1234567890</review_id><review_time>20160614:11:00:47</review_time><status>Accepted</status></payhead></payheads><current_gross_allowance>50481.00</current_gross_allowance><review_gross_allowance>114051.00</review_gross_allowance></review_sr>');

$child = new SimpleXMLElement('<source><payhead><code>DMG</code><old_value>500.00</old_value><new_value>0.00</new_value><review_id>1234567890</review_id><review_time>20160620:12:41:17</review_time><status>Accepted</status></payhead></source>');
$child = $child->xpath('//payhead'); //This is to ignore the xml declaration that is automatically produced by the SimpleXMLElement constructor
$child = $child[0];                 //I've tried LIBXML_NOXMLDECL  but its not working, that's why these two lines.

$parentNode = $parent->xpath('//payheads');
sxml_append($parentNode[0],$child[0]);

var_dump($parent);