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 & + * 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("&","&",$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]