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]