tags:

views:

36

answers:

2

I have a script which collects 4 URL's (XML) using CURL and returns an array with 4 items each ocntaining the results of the URL's.

Here is the array:

array(3) {
  [0]=>
  string(41772) "<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
<status>
  <created_at>Tue Mar 30 20:58:53 +0000 2010</created_at>
  <id>11328253513</id>
  <text>...</text>
  <source...</source>
  <truncated>false</truncated>
  <in_reply_to_status_id></in_reply_to_status_id>
  <in_reply_to_user_id></in_reply_to_user_id>
  <favorited>true</favorited>
  <in_reply_to_screen_name></in_reply_to_screen_name>
  <user>
    <id>1...</id>
    <name>....</name>
</status>
</statuses>
"
  [1]=>
  string(20630) "<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
<status>
  <created_at>Sun Feb 28 14:12:30 +0000 2010</created_at>
  <id>...</id>
  <text>...</text>
  <source>&lt;a

etc...

How can I easily output the XML from the array? I also need to combine the 3 XML structures into one where <statuses> begins and ends in between each array.

+2  A: 

A possible idea would be to :

  • Create a new $destination instance of DOMDocument
    • Initialize it with a <statuses> node
  • For each of your 3 XML strings :
    • load it to another instance of DOMDocument : $currentDocument
    • find the <status> node, with $currentDocument->getElementsByTagName or an equivalent
    • import the <status> node you've just found to the $destination document, with $destination->importNode
  • When the loop over each XML string is finished, the $destination document should contain what you wanted, and you can save it, using $destination->saveXML


And here's a quick example of code that could help you understand what I meant :

First, here's the array of XML strings -- I've made them much shorter, but the idea is the same that what you have :

$strings = array(
  '<?xml version="1.0" encoding="UTF-8"?>
    <statuses type="array"><status>
      <id>ID 1</id>
    </status></statuses>',
  '<?xml version="1.0" encoding="UTF-8"?>
    <statuses type="array"><status>
      <id>ID 2</id>
    </status></statuses>',
  '<?xml version="1.0" encoding="UTF-8"?>
    <statuses type="array"><status>
      <id>ID 3</id>
    </status></statuses>',
);


Let's create the destination document, and put a <statuses> tag in it :

$destination = new DOMDocument();
$destination->formatOutput = true;
$destinationStatuses = $destination->createElement('statuses');
$destination->appendChild($destinationStatuses);


Now, we loop over the 3 XML strings :

foreach ($strings as $str) {
  $current = new DOMDocument();
  $current->loadXML($str);
  $currentStatuses = $current->getElementsByTagName('status');
  foreach ($currentStatuses as $currentStatus) {
    $destinationStatus = $destination->importNode($currentStatus, true);
    $destinationStatuses->appendChild($destinationStatus);
  }
}


For each string, we :

  • Load it to a new DOMDocument
  • Find the <status> tag(s)
  • For each <status> tag, import it to the destination document
  • And add it to its <statuses> tag


And, finally, if we output the content of the new document :

echo '<pre>' . htmlspecialchars($destination->saveXML()) . '</pre>';


We get :

<?xml version="1.0"?>
<statuses>
  <status>
      <id>ID 1</id>
    </status>
  <status>
      <id>ID 2</id>
    </status>
  <status>
      <id>ID 3</id>
    </status>
</statuses>

i.e. our three <status> from the three original strings have been merged into a single XML Document ;-)

Pascal MARTIN
Overkill :) but clean and reliable overkill.
Gordon
More fun than using strings manipulations :-p ;;; and far more reliable than strings manipulations ;;; and in other situations, will work, while strings/regex manipulations won't *(even if, yes, I admit, it's a bit overkill in this precise situation...)*
Pascal MARTIN
No doubt and +1 for the diligence ;)
Gordon
:-) *(I've really started using DOM seriously a couple of weeks ago, and like it more and more ^^ so much easier than regex !)*
Pascal MARTIN
Yup, once you get past the *"Eww, DOM is so huge and difficult"* stage it's really neat to work with. Also much better than SimpleXml.
Gordon
exactly :-D ;; it's hard when you're beginning using it... but so great when you know a bit more.
Pascal MARTIN
Think I might have to give this a try just to learn something new, I do get 'dodgy' characters appearing when using this method though.The above - above solution gives me this txt at the start of the output: string(109960) "
danit
@danit : As you've asked this in another question ( http://stackoverflow.com/questions/2555411/strange-text-when-converting-xml-array-to-xml ), and it's a different problem than the one you first asked here, I suggest we continue there :-) *(I already posted a possible answer)*
Pascal MARTIN
A: 

For a simple merger like this you can also just do:

$xml = implode('', $theArray); 
$xml = str_replace(array('<?xml version="1.0" encoding="UTF-8"?>',
                         '<statuses type="array">',
                         '</statuses>'), '', $xml); 

$xml = '<?xml version="1.0" encoding="UTF-8"?>'
     . '<statuses type="array">'
     . $xml
     . '</statuses>';

Note: untested, but basically all it does is glue all XML documents into one, then remove the XML Prologs and all root nodes, so only the status nodes remain. These are then wrapped into a valid XML skeleton, e.g. prolog and root node again. Done.

If you want to work with the DOM Nodes afterwards, using DOM would be more reliable, since DOM knows what nodes are, while string functions have no clue about them. If you decide to work with DOM, consider loading the documents with load instead of CURL, like shown in Pascal's example - or use the above first and then load that document from the string with loadXml().

Whatever you decide to use though, don't use Regex. That is the road to madness.

Gordon
Using this method I get string(109960) "<?xml version="1.0" encoding="UTF-8"?> on the first line of $xml
danit
@danit did you solve it from the other question or is it still an issue?
Gordon