Page 1 of 1

Critique - XML Parser

Posted: Sun Feb 01, 2009 9:47 am
by infolock

Code: Select all

 
<?php
/**
 * @author Jonathon Hibbard
 * 
 * Parses an XML file and returns a multidimentional array..
 * 
 */
 
class jxml {
  public $debug = false;
  public $_xml = "";
  public function jxml($debug = false) {
    $this->_xml = '';
    if($debug === true) {
      $this->debug = true;
    }
  }
 
  
  
  /**
   * Loads the XML string data into the $_xml private var.
   *
   * @param  string $xml_data // String of XML data..
   * @return boolean          // Returns true
   */
  public function loadXML($xml_data = '') {
    $this->_xml = trim($xml_data);
    if($this->debug == true) echo "\n XML IS : ".$this->_xml." \n";
    return true;
  }
 
  /**
   * Reads the file passed in and creates an array to be used with $this->_xml private var.
   *
   * @param  file     $xml_file // A file that contains the XML information.
   * @return boolean  true/fall // Returns TRUE on success, FALSE on error.
   */
  public function loadFile($xml_file = '') {
    if(!$fp = fopen($xml_file, 'r')) return false;
    $xml = '';
    while (!feof($fp)) $xml .= fread($fp, 4096);
    fclose($fp);
 
    if($this->debug == true) echo "\n\n XML DATA IS AS FOLLOWS : \n $xml \n\n";
 
    $this->_xml = trim($xml);
    return true;
  }
 
  /**
   * Creates a multi-dimensional array for the contents of the XML.
   *
   * @param  boolean $white_space   // When set to TRUE, it will skip whitespace when called.
   * @param  boolean $die_on_error  // If set to TRUE, function will die and clear all XML data on error.
   * @return mixed   $array         // A multi-dimensional array containing the XML data.
   */
  public function toArray($white_space = 1, $die_on_error = 1) {
    $vals = $index = $array = array();
    $parser = xml_parser_create();
 
    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, $white_space);
 
    if(!xml_parse_into_struct($parser, $this->_xml, $vals, $index)) {
      xml_parser_free($parser);
      return false;
    }
    xml_parser_free($parser);
    $i = 0;
    $tagname              = $vals[$i]['tag'];
    $array[$tagname]['@'] = (isset($vals[$i]['attributes']) ? $vals[$i]['attributes'] : array());
    $array[$tagname]["#"] = $this->_xml_depth($vals, $i);
 
    if($this->debug == true) echo "\n\n tagname composition : \n ".print_r($tagname,1)."\n\n array[tagname] composition: \n".print_r($array,1)."\n\n";
 
    return $array;
  }
 
  /**
   * Recursive function to create children in each parent node.
   *
   * @param unknown_type $vals
   * @param unknown_type $i
   * @return unknown
   */
  public function _xml_depth($vals, &$i) {
    $children = array();
 
    if(isset($vals[$i]['value'])) array_push($children, $vals[$i]['value']);
 
    while (++$i < count($vals)) {
      switch ($vals[$i]['type']) {
        case 'open':
          $tagname = (isset($vals[$i]['tag']) ? $vals[$i]['tag'] : '');
          $size    = (isset($children[$tagname]) ? sizeof($children[$tagname]) : 0);
 
          if(isset($vals[$i]['attributes'])) $children[$tagname][$size]['@'] = $vals[$i]["attributes"];
          $children[$tagname][$size]['#'] = $this->_xml_depth($vals, $i);
        break;
 
        case 'cdata':
          array_push($children, $vals[$i]['value']);
        break;
 
        case 'complete':
          $tagname                        = $vals[$i]['tag'];
          $size                           = (isset($children[$tagname]) ? sizeof($children[$tagname]) : 0);
          $children[$tagname][$size]["#"] = (isset($vals[$i]['value']) ? $vals[$i]['value'] : '');
 
          if (isset($vals[$i]['attributes'])) $children[$tagname][$size]['@'] = $vals[$i]['attributes'];
        break;
 
        case 'close':
          return $children;
        break;
      }
    }
 
    return $children;
  }
 
  /**
   * Easy way to keep track of where we are in the stack.
   *
   * @param unknown_type $array
   * @param unknown_type $arrName
   * @param unknown_type $level
   * @return unknown
   */
  public function traverse_xmlize($array, $arrName = "array", $level = 0) {
    foreach($array as $key => $val) {
      if(is_array($val)) {
        traverse_xmlize($val, $arrName . "[" . $key . "]", $level + 1);
      } else {
        $GLOBALS['traverse_array'][] = '$' . $arrName . '[' . $key . '] = "' . $val . "\"\n";
      }
    }
    return 1;
  }
}
?>
 
Usage

Code: Select all

 
$xml = new jxml();
$xml->loadFile($xml_file);
$xml_array = $xml->toArray();
echo "<pre>";
print_r($xml_array);
echo "</pre>";
?>
 

Re: Critique - XML Parser

Posted: Sun Feb 01, 2009 2:53 pm
by John Cartwright

Code: Select all

$xml = new SimpleXMLElement(file_get_contents('http://www.w3schools.com/XML/note.xml'));
 
echo '<pre>';
print_r($xml);
For those of us with SimpleXML extension :)

Re: Critique - XML Parser

Posted: Sun Feb 01, 2009 3:46 pm
by infolock
Yeah, I know about SimpleXML. I use it actually with PHP 5 as I had originally written this class for PHP 4 (added the new OOP crap for 5) :lol:

Guess it's time to retire this class :(

Re: Critique - XML Parser

Posted: Thu Feb 12, 2009 10:11 pm
by josh
I was going to say the same thing but I still think its neat you wrote this. Did you know you can't call print_r within an ob_start() callback? Something about ob_start callbacks can't use output buffering and print_r uses it "under the hood", I'm sure someone could find obscure uses.