home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 August / PCWorld_2001-08_cd.bin / Komunikace / phptriad / phptriadsetup2-11.exe / php / pear / PHPDoc / xmlreader / PhpdocXMLReader.php
PHP Script  |  2001-02-18  |  7KB  |  226 lines

  1. <?php
  2. /**
  3. * Reads XML documents into a multi dimensional Array.
  4. *
  5. * @version $Id: PhpdocXMLReader.php,v 1.4 2001/02/18 16:56:18 uw Exp $
  6. */
  7. class PhpdocXMLReader extends PhpdocObject {
  8.     
  9.     /**
  10.     * PHPDocFileHandler object.
  11.     *
  12.     * @var  object PhpdocFileHandler
  13.     * @see  createFileHandler()
  14.     */
  15.     var $filehandler; 
  16.  
  17.     /**
  18.     * Values array from xml_parse_into_struct().
  19.     *
  20.     * @var  array
  21.     * @see  parse(), stripCloseFromStructvalues(), importXML()
  22.     */
  23.     var $structvalues = array();
  24.     
  25.     /**
  26.     * Parses a given XML file and returns the data as a hash.
  27.     * 
  28.     * Please do not ask me for a in detail explanation of how it is done,
  29.     * the documentation is in the source...
  30.     *
  31.     * @param    string  $filename Name of the xml document
  32.     * @access   public
  33.     * @throws   PhpdocError
  34.     * @see      importXML()
  35.     */    
  36.     function parse($filename) {
  37.     
  38.         if (""==$filename) {
  39.             $this->err[] = new PhpdocError("No filename given.", __FILE__, __LINE__);
  40.             return array();
  41.         }
  42.         
  43.         $parser = xml_parser_create();
  44.         if (!$parser) {
  45.             $this->err = PhpdocError("Can't create a XML Parser.", __FILE__, __LINE__);
  46.             return array();
  47.         }
  48.         xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
  49.         
  50.         $this->createFileHandler();
  51.         $xml = $this->filehandler->getFile($filename);
  52.  
  53.         $values = array();
  54.         $index  = array();
  55.         xml_parse_into_struct($parser, $xml, $values, $index);
  56.         
  57.         xml_parser_free($parser);
  58.  
  59.         $this->structvalues = $values;
  60.         $this->stripCloseFromStructvalues();
  61.         list($data, $last) = $this->importXML();
  62.         $this->structvalues = array();
  63.         
  64.         return $data;
  65.     } // end func parse
  66.  
  67.     /**
  68.     * Creates a PhpdocFileHandler object and saves it to $filehandler if it does not already exist.
  69.     *
  70.     * @see  $filehandler
  71.     */    
  72.     function createFilehandler() {
  73.     
  74.         if (!isset($this->filehandler))
  75.             $this->filehandler = new PhpdocFileHandler;
  76.             
  77.     } // end func createFilehandler
  78.     
  79.     /**
  80.     * Strips all values out of the xml_parse_intro_struct() values array with the type "open".
  81.     *
  82.     * @see  $structvalues 
  83.     */
  84.     function stripCloseFromStructvalues() {
  85.         
  86.         $values = array();
  87.         
  88.         reset($this->structvalues);
  89.         while (list($k, $v) = each($this->structvalues))
  90.             if ("close" != $v["type"])
  91.                 $values[] = $v;
  92.                 
  93.         $this->structvalues = $values;
  94.     } // end func stripCloseFromStructvalues
  95.      
  96.     /**
  97.     * Converts an xml_parse_into_struct value array to an array that's simmilar to phpdocs internal arrays.
  98.     *
  99.     * Well, don't ask me to explain this hack. Just take it as it. For those who want to unterstand and optimize
  100.     * it:
  101.     *  - PHP3 compatibility is a must
  102.     *  - no XML DOM
  103.     *  - no eval(), this can't be optimized by the compiler
  104.     *
  105.     * @param    integer    
  106.     * @param    integer
  107.     * @return   array    $data[0] = daten, $data[1] = some index value used for the recursion
  108.     * @see      addToArray()
  109.     */
  110.     function importXML($start = 0, $allowed_level = 1) {
  111.         
  112.         $data = array();
  113.         $last = 0;
  114.         
  115.         for ($i = $start; $i < count($this->structvalues); $i++) {
  116.             if ($allowed_level != $this->structvalues[$i]["level"]) 
  117.                 break;
  118.             
  119.             $value      = (isset($this->structvalues[$i]["value"])) ? $this->structvalues[$i]["value"] : "";
  120.             $attribs    = (isset($this->structvalues[$i]["attributes"])) ? $this->structvalues[$i]["attributes"] : "";
  121.             $tag        = $this->structvalues[$i]["tag"];
  122.  
  123.             if ("open" == $this->structvalues[$i]["type"]) {
  124.  
  125.                 list($inner, $next) = $this->importXML($i+1, $this->structvalues[$i]["level"] + 1);
  126.                 
  127.                 // append the inner data to the current one
  128.                 $data                = $this->addToArray($data, $tag, $value, $attribs, $inner);
  129.                 
  130.                 // skip some entries in $this->structvalues
  131.                 $i = $next;
  132.                 
  133.             } else {
  134.             
  135.                 // same level, append to the array
  136.                 $data = $this->addToArray($data, $tag, $value, $attribs);
  137.                 
  138.             }
  139.             
  140.             // remember the last index in $this->structvalues we've worked on
  141.             $last = $i;
  142.         }
  143.         
  144.         return array($data, $last);
  145.     } // end func importXML
  146.     
  147.     /**
  148.     * Appends some values to an array
  149.     * Well, don't ask me; just improve it with the remarks on buildXMLResult()
  150.     * @param    array
  151.     * @param    string
  152.     * @param    string    
  153.     * @param    array
  154.     * @param    array
  155.     * @return   array $target
  156.     */
  157.     function addToArray($target, $key, $value = "", $attributes = "", $inner = "") {
  158.  
  159.         if (!isset($target[$key]["value"]) && !isset($target[$key][0])) {
  160.     
  161.             if ("" != $inner)
  162.                 $target[$key] = $inner;
  163.  
  164.             if ("" != $attributes) {
  165.                 reset($attributes);
  166.                 while (list($k, $v) = each($attributes))
  167.                     $target[$key][$k] = $this->xmldecode($v);
  168.             }
  169.                 
  170.             $target[$key]["value"] = $this->xmldecode($value);
  171.         
  172.         } else {
  173.     
  174.             if (!isset($target[$key][0])) {
  175.         
  176.                 $oldvalue = $target[$key];
  177.                 $target[$key] = array();
  178.                 $target[$key][0] = $oldvalue;
  179.             
  180.                 if ("" != $inner)
  181.                     $target[$key][1] = $inner;
  182.  
  183.                 if ("" != $attributes) {
  184.                     reset($attributes);
  185.                     while (list($k, $v)=each($attributes))
  186.                         $target[$key][1][$k] = $this->xmldecode($v);
  187.                 }
  188.                 
  189.                 $target[$key][1]["value"] = $this->xmldecode($value);
  190.                 
  191.             } else {
  192.                 
  193.                 $index = count($target[$key]);
  194.                 
  195.                 if ("" != $inner)
  196.                     $target[$key][$index] = $inner;
  197.  
  198.                 if ("" != $attributes) {
  199.                     reset($attributes);
  200.                     while (list($k, $v) = each($attributes))
  201.                         $target[$key][$index][$k] = $this->xmldecode($v);
  202.                 }
  203.                 
  204.                 $target[$key][$index]["value"] = $this->xmldecode($value);
  205.  
  206.             }
  207.  
  208.         }
  209.     
  210.         return $target;
  211.     } // end func addToArray
  212.     
  213.     /**
  214.     * Replaces some basic entities with their character counterparts.
  215.     * 
  216.     * @param    string  String to decode
  217.     * @return   string  Decoded string
  218.     */
  219.     function xmldecode($value) {
  220.         #return preg_replace( array("@<@", "@>@", "@'@", "@"@", "@&@"), array("<", ">", "'", '"', "&"), $value);
  221.         return utf8_decode(preg_replace( array("@<@", "@>@", "@'@", "@"@", "@&@"), array("<", ">", "'", '"', "&"), $value));
  222.     } // end func xmldecode
  223.  
  224. } // end class PhpdocXMLReader
  225. ?>
  226.