views:

180

answers:

3

I am rebuilding a nodes children by saving them out to an array as strings, trashing them in the XML, inserting a new child node into the array as a string... now I want to loop through the array and write them back out to the original node. The problem is I can't find anything on how to add a child node using a string.

See below for my code. Thanks!!!

$xml = simplexml_load_file($url);

 $questionGroup = $xml->qa[intval($id)];

 $children = array(); //  create empty array

 foreach ($questionGroup->children() as $element) {  //  loop thru children
  array_push($children, $element->asXML()); // save XML into array
 }
 //unset($questionGroup->answer);
 //unset($questionGroup->question);

 //create new node
 $newNode = '<answer><title>'.$title.'</title><description>'.$description.'</description><subName>'.$subName.'</subName><date>'.$date.'</date><timestamp>'.$timestamp.'</timestamp></answer>';

 echo "children count: ".count($children);
 echo "<br /><br />";
 print_r($children);
 echo "<br /><br />";
 // insert new
 array_splice($children,intval($elementIndex),0,$newNode);
 echo "children count: ".count($children);
 echo "<br /><br />";
 print_r($children);
 echo "<br /><br />";
 echo $questionGroup->asXML();
 foreach ($children as $element) {  //  loop thru array 
  echo "<br /><br />";
  echo $element;
  //$questionGroup->addChild(simplexml_load_string($element));  //  add array element to the empty questionGroup

 } 
  echo "<br /><br />";
 echo "questionGroup: ".$questionGroup;

UPDATE: I found a function that I modified and was able to get working:

function append_simplexml(&$simplexml_to, &$simplexml_from)
{
   $childNode = $simplexml_to->addChild($simplexml_from->getName(), "");
    foreach ($simplexml_from->children() as $simplexml_child)
    {
    $simplexml_temp = $childNode->addChild($simplexml_child->getName(), (string) $simplexml_child);
    foreach ($simplexml_child->attributes() as $attr_key => $attr_value)
    {
    $simplexml_temp->addAttribute($attr_key, $attr_value);
    }

   // append_simplexml($simplexml_temp, $simplexml_child);
    }
}

With this usage in my foreach() loop:

foreach ($children as $element) {  //  loop thru array 
 append_simplexml($questionGroup, new SimpleXMLElement($element));
}
A: 

You should be able to do something like this:

$child = new SimpleXMLElement($newNode);

$yourxmlobject->addChild($child);
Franz
Now you still got to get rid of your old element, though, if I am not mistaken.
Franz
I implemented this and it returned this error:Warning: SimpleXMLElement::addChild() [simplexmlelement.addchild]: Element name is requiredaddChild() needs a "name" and only creates (I think) a single, empty node using the passed "name".I've got an array of strings, each looking like this:<answer><title>blah 1</title><description>blah 1</description><subName></subName><date>4:34 pm, Wednesday, November 11, 2009</date><timestamp>20091111163453</timestamp></answer>That I just want to inject into my empty node.BTW, I'm using unset() to remove the nodes, but they are just commented out.
Justin Lee
Oops. Sorry. I misinterpreted something. Looks like you have to manually modify the values which should be much simpler and cleaner than the current approach anyways. Let me come up with something...
Franz
+3  A: 

You can't do that with SimpleXML alone. There is a nice way to do this with the DOM extension and the DOMDocumentFragment class. (Please note that I didn't try to understand your logic in the example provided, but you should be able to implement the simple sample below into your code).

$xml = simplexml_load_string('<root><parent/></root>');
// get the parent node under which you want to insert your XML fragement
$parent = dom_import_simplexml($xml->parent);
// create the XML fragment
$fragment = $parent->ownerDocument->createDocumentFragment();
// append the XML literal to your fragment
$fragment->appendXML('<child id="1"/><child id="2"><grandchild/></child>');
// append the fragment to the parent node
$parent->appendChild($fragment);
echo $xml->asXML();
/*
 * <?xml version="1.0"?>
 * <root><parent><child id="1"/><child id="2"><grandchild/></child></parent></root>
 */

Links:

Stefan Gehrig
This sound very promising! I'll give it a shot when I've got some spare time! Thanks Stefan!!
Justin Lee
+2  A: 

I found a function that I modified and was able to get working:

function append_simplexml(&$simplexml_to, &$simplexml_from)
{
   $childNode = $simplexml_to->addChild($simplexml_from->getName(), "");
    foreach ($simplexml_from->children() as $simplexml_child)
    {
           $simplexml_temp = $childNode->addChild($simplexml_child->getName(), (string) $simplexml_child);
           foreach ($simplexml_child->attributes() as $attr_key => $attr_value)
       {
              $simplexml_temp->addAttribute($attr_key, $attr_value);
       }

      // append_simplexml($simplexml_temp, $simplexml_child);
    }
}

With this usage in my foreach() loop:

foreach ($children as $element) {  //  loop thru array 
    append_simplexml($questionGroup, new SimpleXMLElement($element));
}
Justin Lee
+1 for posting follow up
Henrik Opel