chregu          Wed Apr  4 02:15:58 2001 EDT

  Modified files:              
    /php4/pear/Experimental/XML sql2xml.php 
  Log:
  - new function addArray() for adding Arrays to the xml
  - new function addSql() for providing sql-strings as input
  - constructor takes a dsn or a pear::db object as param (API-Change..)
  - a lot of inline-documentation (not finished...)
  
  
Index: php4/pear/Experimental/XML/sql2xml.php
diff -u php4/pear/Experimental/XML/sql2xml.php:1.5 
php4/pear/Experimental/XML/sql2xml.php:1.6
--- php4/pear/Experimental/XML/sql2xml.php:1.5  Fri Mar 30 04:55:30 2001
+++ php4/pear/Experimental/XML/sql2xml.php      Wed Apr  4 02:15:57 2001
@@ -15,74 +15,174 @@
 // | Authors: Christian Stocker <[EMAIL PROTECTED]>                         |
 // +----------------------------------------------------------------------+
 //
-// $Id: sql2xml.php,v 1.5 2001/03/30 12:55:30 chregu Exp $
+// $Id: sql2xml.php,v 1.6 2001/04/04 09:15:57 chregu Exp $
 
+require_once("PEAR.php");
+
 /**
-* This class takes a PEAR::DB-Result Object (or more than one)
+* This class takes a PEAR::DB-Result Object, a sql-query-string or an array
 *  and returns a xml-representation of it.
 *
 * More docs will follow
 *
+* TODO
+*   -encoding etc, options for header
+*   - ERROR CHECKING
 * Usage example
 *
 * include_once ("DB.php");
 * include_once("XML/sql2xml.php");
 * $db = DB::connect("mysql://root@localhost/xmltest");
-* $xml = new xml_sql2xml;
+* $sql2xml = new xml_sql2xml();
 * $result = $db->query("select * from bands");
-* $xmlstring = $xml->getXML($result,$options));
+* $xmlstring = $sql2xml->getXML($result);
+*
+* or
 *
+* $sql2xml = new xml_sql2xml("mysql://root@localhost/xmltest");
+* $sql2xml->AddSql("select * from bands");
+* $xmlstring = $sql2xml->getXML();
+*
 * more examples and outputs on
 *   http://www.nomad.ch/php/sql2xml
 *   for the time being
 *
 * @author   Christian Stocker <[EMAIL PROTECTED]>
-* @version  $Id: sql2xml.php,v 1.5 2001/03/30 12:55:30 chregu Exp $
+* @version  $Id: sql2xml.php,v 1.6 2001/04/04 09:15:57 chregu Exp $
+* @package  XML
 */
 class XML_sql2xml {
 
     /**
+    * If joined-tables should be output nested.
+    *  Means, if you have joined two or more queries, the later
+    *   specified tables will be nested within the result of the former
+    *   table.
+    *   Works at the moment only with mysql automagically. For other RDBMS
+    *   you have to provide your table-relations by hand (see user_tableinfo)
     *
     * @var  boolean
+    * @see  $user_tableinfo, doSql2Xml(), doArray2Xml();
     */
     var $nested = True;
 
+    /**
+    *
+    * @var   object PEAR::DB
+    * @acces private
+    */
+    var $db = Null;
+
 
     /**
+    * Options to be used in extended Classes (for example in sql2xml_ext).
+    * They are passed with SetOptions as an array (arrary("user_optpaions" = array());
+    *  and can then be accessed with $this->user_options["bla"] from your
+    *  extended classes for additional features.
+    *  This array is not use in this base class, it's only for passing easy parameters
+    *  to extended classes.
     *
-    * @var  boolean
+    * @var      array
     */
-    var $user_options = False;
+    var $user_options = array();
 
 
     /**
+    * The DomDocument Object to be used in the whole class
     *
-    * @var  object  domxml
+    * @var      object  DomDocument
+    * @acces    private
     */
     var $xmldoc;
 
 
     /**
+    * The Root of the domxml object
+    * I'm not sure, if we need this as a class variable....
     *
-    * @var  string
+    * @var      object DomNode
+    * @acces    private
     */
-    var $xmlroot = "";
+    var $xmlroot;
 
 
     /**
+    * This array is used to give the structure of your database to the class.
+    *  It's especially useful, if you don't use mysql, since other RDBMS than
+    *  mysql are not able at the moment to provide the right information about
+    *  your database structure within the query. And if you have more than 2
+    *  tables joined in the sql it's also not possible for mysql to find out
+    *  your real relations.
+    *  The parameters are the same as in fieldInfo from the PEAR::DB and some
+    *   additional ones. Here they come:
+    *  From PEAR::DB->fieldinfo:
     *
-    * @var  boolean
+    *    $tableInfo[$i]["table"]    : the table, which field #$i belongs to.
+    *           for some rdbms/comples queries and with arrays, it's impossible
+    *           to find out to which table the field actually belongs. You can
+    *           specify it here more accurate. Or if you want, that one fields
+    *           belongs to another table, than it actually says (yes, there's
+    *           use for that, see the upcoming tutorial ...)
+    *
+    *    $tableInfo[$i]["name"]     : the name of field #$i. if you want another
+    *           name for the tag, than the query or your array provides, assign
+    *           it here.
+    *
+    *   Additional info
+    *     $tableInfo["parent_key"][$table]  : index of the parent key for $table.
+    *           this is the field, where the programm looks for changes, if this
+    *           field changes, it assumes, that we need a new "rowset" in the
+    *           parent table.
+    *
+    *     $tableInfo["parent_table"][$table]: name of the parent table for $table.
+    *
+    * @var      array
+    * @acces    private
     */
-    var $user_tableInfo = False;
+    var $user_tableInfo = array();
 
 
     /**
-    *
+    * Constructor
+    * The Constructor can take a Pear::DB "data source name" (eg.
+    *  "mysql://user:passwd@localhost/dbname") and will then connect
+    *  to the DB, or a PEAR::DB object link, if you already connected
+    *  the db before.
+    "  If you provide nothing as $dsn, you only can later add stuff with
+    *   a pear::db-resultset or as an array. providing sql-strings will
+    *   not work.
+    * the $root param is used, if you want to provide another name for your
+    *  root-tag than "root". if you give an empty string (""), there will be no
+    *  root element created here, but only when you add a resultset/array/sql-string.
+    *  And the first tag of this result is used as the root tag.
     *
-    * @param  string
+    * @param  $dsn string with PEAR::DB "data source name" or object DB object
+    * @param  $root string of the name of the xml-doc root element.
     */
-    function XML_sql2xml ($root = "root") {
+    function XML_sql2xml ($dsn=False,$root = "root") {
+
+        if (DB::isError($dsn)) {
+            print "The given param for XML_sql2xml was not valid in file ".__FILE__." 
+at line ".__LINE__."<br>\n";
+            return new DB_Error($dsn->code,PEAR_ERROR_DIE);
+        }
 
+        // if it's a string, then it must be a dsn-identifier;
+        if (is_string($dsn)) {
+            $this->db = DB::Connect($dsn);
+            if (DB::isError($this->db))
+            {
+                print "The given dsn for XML_sql2xml was not valid in file 
+".__FILE__." at line ".__LINE__."<br>\n";
+                return new DB_Error($this->db->code,PEAR_ERROR_DIE);
+            }
+
+        }
+        // if parent class is db_common, then it's already a connected identifier
+        elseif (get_parent_class($dsn) == "db_common")
+        {
+            $this->db = $dsn;
+        }
+
+
         $this->xmldoc = domxml_new_xmldoc('1.0');
         if ($root) {
             $this->xmlroot = $this->xmldoc->add_root($root);
@@ -91,59 +191,114 @@
     }
 
     /**
-      * Adds an aditional resultset to the xml-document
-      *
-      * @param    Object result result from a DB-query
-      * @param    array  mixed   options to be passed (does it need that?)
-      * @return   string  xml
-      * @access   public
-      */
-    function addResult($result, $options = False)
+    * General method for adding new resultsets to the xml-object
+    *  Give a sql-query-string, a pear::db_result object or an array as
+    *  input parameter, and the method calls the appropriate method for this
+    *  input and adds this to $this->xmldoc
+    *
+    * @param    $resultset string sql-string, or object db_result, or array
+    * @access   public
+    * @see      addResult(), addSql(), addArray()
+    */
+    function add ($resultset)
     {
-        $this->doSql2Xml($result, $options);
+        // if string, then it's a query...
+        if (is_string($resultset)) {
+            $this->AddSql($resultset);
+        }
+        // if array, then it's an array...
+        elseif (is_array($resultset)) {
+            $this->AddArray($resultset);
+        }
+
+        if (get_class($resultset) == "db_result") {
+            $this->AddResult($resultset);
+        }
     }
 
     /**
+    * Adds an additional pear::db_result resultset to $this->xmldoc
+    *
+    * @param    Object db_result result from a DB-query
+    * @see      doSql2Xml()
+    * @access   public
+    */
+    function addResult($result)
+    {
+        $this->doSql2Xml($result);
+    }
+
+    /**
+    * Adds an aditional resultset generated from an sql-statement
+    *  to $this->xmldoc
+    *
+    * @param    string sql a string containing an sql-statement.
+    * @access   public
+    * @see      doSql2Xml()
+    */
+    function addSql($sql)
+    {
+        $result = $this->db->query($sql);
+        $this->doSql2Xml($result);
+    }
+
+    /**
+    * Adds an aditional resultset generated from an Array
+    *  to $this->xmldoc
+    * TODO: more explanation, how arrays are transferred
+    *
+    * @param    array multidimensional array.
+    * @access   public
+    * @see      doArray2Xml()
+    */
+    function addArray ($array)
+    {
+        $parent_row = $this->insertNewResult(&$metadata);
+        $this->DoArray2Xml($array,$parent_row);
+    }
+
+    /**
     * Returns an xml-string with a xml-representation of the resultsets.
     *
     * The resultset can be directly provided here, or if you need more than one
-    * in your xml, then you have to provide each of them with addResult befor getXML
+    * in your xml, then you have to provide each of them with add() before you
+    * call getXML, but the last one can also be provided here.
     *
     * @param    Object  result result from a DB-query
-    * @param    array   mixed   options to be passed (does it need that?)
     * @return   string  xml
     * @access   public
     */
-    function getXML($result = False, $options = False)
+    function getXML($result = Null)
     {
-        return domxml_dumpmem($this->getXMLObject($result, $options));
+        return domxml_dumpmem($this->getXMLObject($result));
     }
 
     /**
-      * Returns an xml DomDocument Object with a xml-representation of the resultsets.
-      *
-      * The resultset can be directly provided here, or if you need more than one
-      * in your xml, then you have to provide each of them with addResult befor getXML
-      *
-      * @param    Object result result from a DB-query
-      * @param    array  mixed   options to be passed (does it need that?)
-      * @return   Object DomDocument
-      * @access   public
-      */
-    function getXMLObject($result = False, $options = False) {
+    * Returns an xml DomDocument Object with a xml-representation of the resultsets.
+    *
+    * The resultset can be directly provided here, or if you need more than one
+    * in your xml, then you have to provide each of them with add() before you
+    * call getXMLObject, but the last one can also be provided here.
+    *
+    * @param    Object result result from a DB-query
+    * @return   Object DomDocument
+    * @access   public
+    */
+    function getXMLObject($result = Null)
+    {
         if ($result) {
-            $this->doSql2Xml($result, $options);
+            $this->add ($result);
         }
         return $this->xmldoc;
     }
 
     /**
-    * 
-    * @param    
-    * @param    boolean
-    * @return   object DomDocument
+    * For adding db_result-"trees" to $this->xmldoc
+    * @param    Object db_result
+    * @access   private
+    * @see      addResult(),addSql()
     */
-    function doSql2Xml($result, $options = False)
+    function doSql2Xml($result)
     {
 
         if (DB::IsError($result)) {
@@ -151,15 +306,8 @@
             new DB_Error($result->code,PEAR_ERROR_DIE);
         }
 
-        //set options
-        if (is_array($options))
-        {
-            foreach ($options as $option => $value)
-            {
-                $this->setOption($option, $value);
-            }
-        }
         //user should be able to give his own tableInfo-array, but not implemented yet
+
         if (! ($tableInfo = $result->tableInfo(False)))
         {
             //emulate tableInfo. this can go away, if every db supports tableInfo
@@ -203,12 +351,12 @@
         }
 
         // end initialize
-        
+
         // if user made some own tableInfo data, merge them here.
-        if ($this->user_tableInfo) 
+        if ($this->user_tableInfo)
         {
             $tableInfo = $this->array_merge_clobber($tableInfo,$this->user_tableInfo);
-        }        
+        }
         $parent[root] = $this->insertNewResult(&$tableInfo);
 
         while ($FirstFetchDone || $res = $result->FetchRow($fetchmode))
@@ -255,31 +403,84 @@
         return $this->xmldoc;
     }
 
-    
     /**
+    * For adding whole arrays to $this->xmldoc
     *
-    * @param
-    * @param
-    * @return
+    * @param    array
+    * @param    Object domNode
+    * @access   private
+    * @see      addArray()
     */
-    function setOption($option, $value)
-    {
-        if (isset($this->$option)) {
-            $this->$option = $value;
+
+    function DoArray2Xml ($array, $parent) {
+        while (list($key, $val) = each($array))
+            {
+                $tableInfo[$key]["table"]= "result";
+                $tableInfo[$key]["name"] = $key;
+            }
+        if ($this->user_tableInfo)
+        {
+            $tableInfo = $this->array_merge_clobber($tableInfo,$this->user_tableInfo);
+        }
+
+        foreach ($array as $key=>$value)
+        {
+            if (is_array($value) ) {
+                if (is_int($key) )
+                {
+                    $valuenew = array_slice($value,0,1);
+                    $keynew = array_keys($valuenew);
+                    $keynew = $keynew[0];
+                }
+                else
+                {
+                    $valuenew = $value;
+                    $keynew = $key;
+                }
+                $rec2 = $this->insertNewRow($parent, $valuenew, $keynew, &$tableInfo);
+                $this->DoArray2xml($value,$rec2);
+            }
+            else {
+                $this->insertNewElement($parent, $array, $key, &$tableInfo,&$subrow);
+            }
+        }
+
+    }
+
+
+
+    /**
+    * This method sets the options for the class
+    *  One can only set variables, which are defined at the top of
+    *  of this class.
+    *
+    * @param    array   options to be passed to the class
+    * @access   public
+    * @see      $nested,$user_options,$user_tableInfo
+    */
 
-            return True;
+    function setOptions($options) {
+    //set options
+        if (is_array($options))
+        {
+            foreach ($options as $option => $value)
+            {
+                if (isset($this->$option)) {
+                    $this->$option = $value;
+                }
+
+            }
         }
-        return False;
-        //        return $this->raiseError("unknown option $option");
     }
 
-// this are the functions, which are intended to be overriden in user classes
+    // these are the functions, which are intended to be overriden in user classes
 
     /**
     *
-    * @param    
+    * @param
     * @return   object  DomNode
     * @abstract
+    * @access   private
     */
     function insertNewResult(&$metadata)
     {
@@ -289,22 +490,23 @@
             return $this->xmldoc->add_root("result");
     }
 
-    
+
     /**
     *
     * @param    object  DomNode
-    * @param    
-    * @param    
-    * @param    
-    * @return   
+    * @param
+    * @param
+    * @param
+    * @return
     * @abstract
+    * @acces private
     */
     function insertNewRow($parent_row, $res, $key, &$metadata)
     {
         return  $parent_row->new_child("row", NULL);
     }
 
-    
+
     /**
     *
     * @param    object  DomNode
@@ -312,35 +514,45 @@
     * @param
     * @param
     * @param
-    * @return 
+    * @return
     * @abstract
+    * @acces private
     */
     function insertNewElement($parent, $res, $key, &$metadata, &$subrow)
     {
         return  $parent->new_child($metadata[$key]["name"], 
$this->xml_encode($res[$key]));
     }
 
-    
+
     /**
     *
-    * @param    
-    * @param    
     * @param
+    * @param
+    * @param
     * @abstract
+    * @acces private
     */
     function addTableInfo($key, $value, &$metadata) {
 
     }
-    
+
+    // end functions, which are intended to be overriden in user classes
+
+    // here come some helper functions...
+
     /**
+    * make utf8 out of the input data and escape & with &amp;
+    *  I'm not sure, if this is the standard way, but it works for me.
     *
-    * @param    
-    * @abstract
+    * @param    string text to be utfed.
+    * @acces private
     */
-    function xml_encode ($text) {
+    function xml_encode ($text)
+    {
         $text = utf8_encode(ereg_replace("&","&amp;",$text));
         return $text;
     }
+
     //taken from [EMAIL PROTECTED] at 
http://www.php.net/manual/en/function.array-merge-recursive.php
     /**
     * There seemed to be no built in function that would merge two arrays recursively 
and clobber
@@ -349,12 +561,12 @@
     *
     *   So here's a cross between array_merge and array_merge_recursive
     **/
-
     /**
     *
-    * @param  
-    * @param      
-    * @abstract
+    * @param    array first array to be merged
+    * @param    array second array to be merged
+    * @return   array merged array
+    * @acces private
     */
     function array_merge_clobber($a1,$a2)
     {
@@ -373,6 +585,5 @@
         }
         return $newarray;
     }
-    
 }
 ?>

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to