{
$this->doxmlstring2xml($string,$xpath);
}
/**
* 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)
{
/* if there are {} expressions in the sql query, we assume its an xpath expression to
* be evaluated.
*/
if (preg_match_all ("/\{([^\}]+)\}/i",$sql,$matches))
{
foreach ($matches[1] as $match)
{
$sql = preg_replace("#\{".preg_quote($match)."\}# ", $this->getxpathvalue($match),$sql);
}
}
$result = $this->db->query($sql);
//very strange
if (pear::iserror($result->result)) {
print "you have an sql-error:<br>".$result->result->userinfo;
print "<br>";
new db_error($result->result->code,pear_error_die);
}
$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 add() before you
* call getxml, but the last one can also be provided here.
*
* @param mixed $result result object from a db-query
* @return string xml
* @access public
*/
function getxml($result = null)
{
$xmldoc = $this->getxmlobject($result);
return $xmldoc->dumpmem();
}
/**
* 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 mixed $result result object from a db-query
* @return object domdocument
* @access public
*/
function getxmlobject($result = null)
{
if ($result) {
$this->add ($result);
}
return $this->xmldoc;
}
/**
* for adding db_result-"trees" to $this->xmldoc
* @param object db_result
* @access private
* @see addresult(),addsql()
*/
function dosql2xml($result)
{
if (db::iserror($result)) {
print "error in file ".__file__." at line ".__line__."<br>\n";
print $result->userinfo."<br>\n";
new db_error($result->code,pear_error_die);
}
// the method_exists is here, cause tableinfo is only in the cvs at the moment
// be careful: if you have fields with the same name in different tables, you will get errors
// later, since db_fetchmode_assoc doesnt differentiate that stuff.
$this->lastresult = &$result;
if (!method_exists($result,"tableinfo") || ! ($tableinfo = $result->tableinfo(false)))
{
//emulate tableinfo. this can go away, if every db supports tableinfo
$fetchmode = db_fetchmode_assoc;
$res = $result->fetchrow($fetchmode);
$this->nested = false;
$i = 0;
while (list($key, $val) = each($res))
{
$tableinfo[$i]["table"]= $this->tagnameresult;
$tableinfo[$i]["name"] = $key;
$resfirstrow[$i] = $val;
$i++;
}
$res = $resfirstrow;
$firstfetchdone = true;
$fetchmode = db_fetchmode_ordered;
}
else
{
$firstfetchdone = false;
$fetchmode = db_fetchmode_ordered;
}
// initialize db hierarchy…
$parenttable = "root";
$tableinfo["parent_key"]["root"] = 0;
foreach ($tableinfo as $key => $value)
{
if (is_int($key))
{
// if the sql-query had a function the table starts with a # (only in mysql i think….), then give the field the name of the table before…
if (preg_match ("/^#/",$value["table"]) || strlen($value["table"]) == 0) {
$value["table"] = $tableinfo[($key – 1)]["table"] ;
$tableinfo[$key]["table"] = $value["table"];
}
if (!isset($tableinfo["parent_table"]) || is_null($tableinfo["parent_table"][$value]["table"]]))
{
$tableinfo["parent_key"][$value]["table"]] = $key;
$tableinfo["parent_table"][$value]["table"]] = $parenttable;
$parenttable = $value["table"] ;
}
}
//if you need more tableinfo for later use you can write a function addtableinfo..
$this->addtableinfo($key, $value, &$tableinfo);
}
// end initialize
// if user made some own tableinfo data, merge them here.
if ($this->user_tableinfo)
{
$tableinfo = $this->array_merge_clobber($tableinfo,$this->user_tableinfo);
}
$parent[root] = $this->insertnewresult(&$tableinfo);
//initialize $resold to get rid of warning messages;
$resold[0] = "thisvalueisimpossibleforthefirstfieldinthefirstrow";
while ($firstfetchdone == true || $res = $result->fetchrow($fetchmode))
{
//firstfetchdone is only for emulating tableinfo, as long as not all dbs support tableinfo. can go away later
$firstfetchdone = false;
while (list($key, $val) = each($res))
{
if ($resold[$tableinfo]["parent_key"][$tableinfo][$key]["table"]]] != $res[$tableinfo]["parent_key"][$tableinfo][$key]["table"]]] || !$this->nested)
{
if ($tableinfo["parent_key"][$tableinfo][$key]["table"]] == $key )
{
if ($this->nested || $key == 0)
{
$parent[$tableinfo][$key]["table"]] = $this->insertnewrow($parent[$tableinfo]["parent_table"][$tableinfo][$key]["table"]]], $res, $key, &$tableinfo);
}
else
{
$parent[$tableinfo][$key]["table"]]= $parent[$tableinfo]["parent_table"][$tableinfo][$key]["table"]]];
}
//set all children entries to somethin stupid
foreach($tableinfo["parent_table"] as $pkey => $pvalue)
{
if ($pvalue == $tableinfo[$key]["table"])
{
$resold[$tableinfo]["parent_key"][$pkey]]= "thisisjustaplaceholder";
}
}
}
if ( $parent[$tableinfo][$key]["table"]] != null)
{
$this->insertnewelement($parent[$tableinfo][$key]["table"]], $res, $key, &$tableinfo, &$subrow);
}
}
}
$resold = $res;
unset ($subrow);
}
return $this->xmldoc;
}
/**
* for adding whole arrays to $this->xmldoc
*
* @param array
* @param object domnode
* @access private
* @see addarray()
*/
function doarray2xml ($array, $parent) {
while (list($key, $val) = each($array))
{
$tableinfo[$key]["table"]= $this->tagnameresult;
$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
* @param boolean if the old suboptions should be deleted
* @access public
* @see $nested,$user_options,$user_tableinfo
*/
function setoptions($options,$delete = false) {
//set options
if (is_array($options))
{
foreach ($options as $option => $value)
{
if (isset($this->{$option}))
