2

I have a simple xml object like this as a result of Zend_Rest_Client_Result Object.

<userdetails>
  <name value="jake"/>
  <type value="user"/>
  <attribute name="fname">
    <value>Jake</value>
  </attribute>
  <attribute name="lname">
    <value>Gordon</value>
  </attribute>
  <attribute name="phone">
    <value>123-555-1234</value>
    <value>999-888-7777</value> 
  </attribute>
 </userdetails>

How can I create an array like this from the above XML object using PHP?

 $userDetails = array();
 $userDetails["name"] = "jake";
 $userDetails["type"] = "user";
 $userDetails["fname"] = "Jake";
 $userDetails["lname"] = "Gordon";
 $userDetails["phone"][0] = "123-555-1234";
 $userDetails["phone"][1] = "123-555-1234";

Thanks,

2 Answers 2

1
$xml = '<userdetails><name value="jake"/><type value="user"/><attribute name="fname"><value>Jake</value></attribute><attribute name="lname"><value>Gordon</value></attribute><attribute name="phone"><value>123-555-1234</value><value>999-888-7777</value></attribute></userdetails>';

$simple = new SimpleXMLElement($xml);
$array = array();

if(isset($simple->name))
  $array['name'] = (string) $simple->name->attributes()->value;

if(isset($simple->type))
  $array['type'] = (string) $simple->type->attributes()->value;

if($foreach = $simple->xpath('//attribute[@name="fname"]/value'))
{
  foreach($foreach as $node)
  {
    $array['fname'] = (string) $node;
  }
}

if($foreach = $simple->xpath('//attribute[@name="lname"]/value'))
{
  foreach($foreach as $node)
  {
    $array['lname'] = (string) $node;
  }
}

if($foreach = $simple->xpath('//attribute[@name="phone"]/value'))
{
  $array['phone'] = array();
  foreach($simple->xpath('//attribute[@name="phone"]/value') as $node)
  {
    $array['phone'][] = (string) $node;
  }
}

print_r($array);
Sign up to request clarification or add additional context in comments.

2 Comments

Quick Question.. PHP gives warnings if the fname or lname or phone attribute does not exist, but is used in the foreach loop. How can I protect my code against that?
Store the result of the xpath search into a variable before the foreach loop, and test against the variable not being empty. See my updated answer.
0
function xmlstr_to_array($xmlstr) {
  $doc = new DOMDocument();
  $doc->loadXML($xmlstr);
  return domnode_to_array($doc->documentElement);
}

function domnode_to_array($node) {
  $output = array();
  switch ($node->nodeType) {
   case XML_CDATA_SECTION_NODE:
   case XML_TEXT_NODE:
    $output = trim($node->textContent);
   break;
   case XML_ELEMENT_NODE:
    for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) {
     $child = $node->childNodes->item($i);
     $v = domnode_to_array($child);
     if(isset($child->tagName)) {
       $t = $child->tagName;
       if(!isset($output[$t])) {
        $output[$t] = array();
       }
       $output[$t][] = $v;
     }
     elseif($v) {
      $output = (string) $v;
     }
    }
    if(is_array($output)) {
     if($node->attributes->length) {
      $a = array();
      foreach($node->attributes as $attrName => $attrNode) {
       $a[$attrName] = (string) $attrNode->value;
      }
      $output['@attributes'] = $a;
     }
     foreach ($output as $t => $v) {
      if(is_array($v) && count($v)==1 && $t!='@attributes') {
       $output[$t] = $v[0];
      }
     }
    }
   break;
  }
  return $output;
}
?>

Another quick and dirty method is:

<?php
  $a = json_decode(json_encode((array) simplexml_load_string($s)),1);
?>

This is less robust and will create problem you code where to contain CDATA nodes as well.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.