[development] development Digest, Vol 99, Issue 69

Karl Giesing khzmusik at hotmail.com
Fri Mar 25 15:25:54 UTC 2011


> I've tried simplexml and a few third-party scripts, one that loads the > xml into an associative array rather than an object, and nothing lets me > get at 'red' or 'blue'. 
I needed something similar for my module. First of all, I wanted it to be compatible with PHP4. This means I needed to use xml_parser functions. Second, I didn't want the user to have to install another module or library.
I ended up using two functions (one is recursive):
/** * Takes an XML string, and returns a multidimensional array. Each "dimension" * may be a text string, a key-value array of tag attributes, and/or another * multidimensional array containing child nodes. * * @param $string *     String containing XML data to parse * @return *     Multidimensional array with attributes, values, and children */function _discogs_xml_to_array(&$string) {  $parser = xml_parser_create();  xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);  xml_parse_into_struct($parser, $string, $vals, $index);  xml_parser_free($parser);
  $multi_array = array();  foreach ($vals as $val) {    $tag = $val['tag'];    if ($val['type'] == 'open') {      if (isset($multi_array[$tag])) {        if (isset($multi_array[$tag][0])) {          $multi_array[$tag][]=array();        }        else {          $multi_array[$tag]=array($multi_array[$tag], array());        }        $cv = &$multi_array[$tag][count($multi_array[$tag])-1];      }      else {        $cv = &$multi_array[$tag];      }      if (isset($val['attributes'])) {        foreach ($val['attributes'] as $k => $v) {          $cv['_attributes'][$k] = $v;        }      }      $cv['_nodes'] = array();      $cv['_nodes']['_recursion'] = &$multi_array;      $multi_array = &$cv['_nodes'];    }    elseif ($val['type'] == 'complete') {      if (isset($multi_array[$tag])) {        if (isset($multi_array[$tag][0])) {          $multi_array[$tag][] = array();        }        else {          $multi_array[$tag] = array($multi_array[$tag], array());        }        $cv = &$multi_array[$tag][count($multi_array[$tag])-1];      }      else {        $cv = &$multi_array[$tag];      }      if (isset($val['attributes'])) {        foreach ($val['attributes'] as $k => $v) {          $cv['_attributes'][$k] = $v;        }      }      if (isset($val['value'])) {        $cv['value'] = trim($val['value']);      }    }    elseif ($val['type'] == 'close') {      $multi_array = &$multi_array['_recursion'];    }  }  // Clean up the recursion and merge attributes with child nodes  $multi_array = _discogs_xml_clean($multi_array);
  return $multi_array;}
/** * Helper function for _discogs_xml_to_array. * * Cleans up the array structure, by getting rid of the recursive data, and * merging the values, attributes and child nodes. * * @param array $old_array *   Old array to clean up * @return array $new_array *   Cleaned up array */function _discogs_xml_clean($old_array) {  // Double check that it's an array, for recursion  if (!is_array($old_array)) {    return $old_array;  }  foreach ($old_array as $k => $v) {    if ($k === '_recursion') {      unset($old_array[$k]);    }    elseif (is_array($old_array[$k]['_nodes']) && is_array($old_array[$k]['_attributes'])) {      $old_nodes = _discogs_xml_clean($old_array[$k]['_nodes']);      $new_merged = array_merge($old_array[$k]['_attributes'], $old_nodes);      $new_array[$k] = $new_merged;    }    elseif (isset($old_array[$k]['value']) && is_array($old_array[$k]['_attributes'])) {      $value['value'] = trim($old_array[$k]['value']);      $new_merged = array_merge($old_array[$k]['_attributes'], $value);      $new_array[$k] = $new_merged;    }    elseif (is_array($old_array[$k]['_nodes'])) {      $new_array[$k] = _discogs_xml_clean($old_array[$k]['_nodes']);    }    elseif (isset($old_array[$k]['_attributes'])) {      $new_array[$k] = $old_array[$k]['_attributes'];    }    elseif (isset($old_array[$k]['value'])) {      $new_array[$k] = $old_array[$k]['value'];    }    else {      $old_nodes = _discogs_xml_clean($old_array[$k]);      $new_array[$k] = $old_nodes;    }  }  return $new_array;}
So, if you passed your XML file to the first function, this would be the resulting multidimensional array:
Array(  [this] => Array    (      [that] => Array        (          [0] => Array            (              [parm1] => a              [parm2] => b              [parm3] => c              [value] => red            )
          [1] => Array            (              [parm1] => e              [parm2] => f              [parm3] => d              [value] => blue            )        )    ))
It's complicated, but it works.
-Karl. 		 	   		  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.drupal.org/pipermail/development/attachments/20110325/70cc9136/attachment-0001.html 


More information about the development mailing list