;
* @copyright Akili AS, June 2003
* @access public
* @package XHTML
*/
class XHTMLDoc
{
//{{{ Class members
/**
* A reference to the root XmlNode of the XML tree representing the XHTML document
* @access private
*/
var $_xmlTree;
/**
* This is the declaration which appears at the top of the XHTML document
* @access private
*/
var $_docType;
/**
* Elements in the document, which have an id attribute.
* @access private
*/
var $_elements;
/**
* The XML parser.
* @access private
*/
var $_parser;
//}}} End class member declarations
//{{{Constructor
/**
* XHTMLDoc constructor
*
* @param string $document Either a string containing the XHTML document, or the
* filename which contains it.
* @access public
*/
function XHTMLDoc( $document )
{
$this->_parser = new XmlParser();
if (strlen($document) < 100 && is_file($document))
$this->_parser->parseFile($document);
else
$this->_parser->parseString($document);
$this->_xmlTree = $this->_parser->getRootNode();
if (is_object($this->_xmlTree))
{
$this->_findIDElements($this->_xmlTree);
$this->_docType = $this->_parser->doctype;
$this->_parser->reset();
}
}//}}}end Constructor
//{{{_findIDElements
/**
* Find all elements which have an id attribute
*
* @param object XmlNode &$node reference to a XMLNode
* @access private
*/
function _findIDElements( &$node )
{
if (!$this->_checkAssert('_findIDElements',
'is_object($param)',
'INTERNAL ERROR:
parameter $node is not an XmlNode',
$node))
{
return false;
}
$children = &$node->getChildren(NUMERIC);
$id = $node->getAttribute('id');
if ($id !== null)
{
$this->_elements[$id] = &$node;
}
$j = count($children);
for ($i = 0; $i < $j; ++$i)
{
$this->_findIDElements( $children[$i] );
}
}//}}}end function _findFormElements
//{{{setValue
/**
* Set the value of the element identified by $id
*
* @param string $id the value of the id attribute of a XHTML element
* (note: lowercase, ie. not ID)
* @param string $value The value to assign to the element.
* @access public
*/
function setValue( $id, $value )
{
if (!$this->_checkID('setValue', $id))
return;
$this->_elements[$id]->setValue($value);
}//}}}end function setValue
//{{{appendValue
/**
* Adds the value to the end of the element identified by $id's content
*
* @param string $id the value of the id attribute of a XHTML element (note: lowercase, ie. not ID)
* @param string $value The value to assign to the element.
* @access public
*/
function appendValue( $id, $value )
{
if (!$this->_checkID('appendValue', $id))
return;
$this->_elements[$id]->appendValue($value);
}//}}}end function appendValue
//{{{addAttribute
/**
* Add a attribute to the element identified by id
*
* @param string $id the value of the id attribute of a XHTML element
* (note: lowercase, ie. not ID)
* @param string $name Name of the attribute to add to the element
* @param string $value The value to assign to the attribute.
* @access public
*/
function addAttribute( $id, $name, $value )
{
if (!$this->_checkID('addAttribute', $id))
return;
$this->_elements[$id]->addAttribute($name, $value);
}//}}}end function addAttribute
//{{{addAttributes
/**
* Similar to XHTMLDoc::addAttribute() except this one lets you add multiple attributes at once
*
* @param string $id the value of the id attribute of a XHTML element
* (note: lowercase, ie. not ID)
* @param string $attributes an associative array of attribute name =>
* attribute value pairs
* @access public
*/
function addAttributes( $id, $attributes )
{
if (!$this->_checkID('addAttributes', $id))
return;
foreach($attributes as $attrName => $attrValue)
{
$this->_elements[$id]->addAttribute($attrName, $attrValue);
}
}//}}}end function addAttributes
//{{{addNode
/**
* Add a XmlNode to the children of the node identified by $id
*
* @param string $id the value of the id attribute of a XHTML element
* (note: lowercase, ie. not ID)
* @param object XmlNode $node The node to add
* @access public
*/
function addNode( $id, $node )
{
if (!$this->_checkID('addNode', $id))
return;
$this->_elements[$id]->addChild('.', $node);
$this->_findIDElements($node);
}//}}}end function addNode
//{{{remIDAttrib
/**
* Remove the ID attribute from all nodes
*
* @access public
*/
function remIDAttrib( )
{
foreach ($this->_elements as $key=>$value)
{
$this->_elements[$key]->remAttribute('id');
}
}//}}}end function remIDAttrib
//{{{insertXHTMLDoc
/**
* Add a XHTML docuemnt to the xmltree, as a child of the node identified by $id
*
* @param string $id the value of the id attribute of a XHTML element
* (note: lowercase, ie. not ID)
* @param string $doc Either a string containing the document, or a filename of a
* file containing the document.
* @access public
*/
function insertXHTML( $id, $doc)
{
if (!$this->_checkID('addNode', $id))
return;
if (strlen($doc) < 100 && is_file($doc))
$this->_parser->parseFile($doc);
else
$this->_parser->parseString($doc);
$root = $this->_parser->getRootNode();
$this->addNode($id, $root);
$this->_findIDElements($this->_xmlTree);
$this->_parser->reset();
}//}}}end function insertXHTMLDoc
//{{{getRootNode
/**
* Get the root node of the XHTML document
*
* @return object XmlNode The root node of the XML tree representing the XHTML document
* @access public
*/
function getRootNode( )
{
return $this->_xmlTree;
}//}}}end function getRootNode
//{{{getDoc
/**
* Get the XHTML document as a string
*
* @return string string representation of this XHTML document
* @access public
*/
function getDoc( )
{
if (!$this->_checkAssert('getDoc',
'!is_null($this->_xmlTree)',
'XHTML document is empty'))
{
return;
}
return $this->_docType."\n".$this->_xmlTree->getXmlString();
}//}}}end function getDoc
//{{{_checkID
/**
* @access private
*/
function _checkID($funcName, $id)
{
if (!assert ('isset($this->_elements[$id])'))
{
$dbt = debug_backtrace();
$errorMsg = 'Assertion failed in call to XHTMLDoc::'.$funcName.':
';
$errorMsg .= 'There is no document element with the id '.$id.'
';
$errorMsg .= 'This method was called from '.$dbt[1]['file'].':'.$dbt[1]['line'];
$errorMsg .= 'Available elements are:';
echo $errorMsg;
if (is_array($this->_elements))
print_r(array_keys($this->_elements));
echo '
';
$this->_printStackTrace( $dbt );
return 0;
}
return 1;
}//}}}end function _checkID
//{{{_checkAssert
/**
* @access private
*/
function _checkAssert($funcName, $assert, $msg, $param = null)
{
if (!assert ($assert))
{
$dbt = debug_backtrace();
$errorMsg = 'Assertion failed in call to XHTMLDoc::'.$funcName.':
';
$errorMsg .= 'This method was called from '.$dbt[1]['file'].':'.$dbt[1]['line'];
$errorMsg .= '
'.$msg.'';
echo $errorMsg;
$this->_printStackTrace( $dbt );
return 0;
}
return 1;
}//}}}end function _checkAssert
//{{{_printStackTrace
/**
* Prints a stacktrace of the callstack
*
* @access private
*/
function _printStackTrace( $dbt )
{
if ($dbt === null)
$dbt = debug_backtrace();
echo 'Complete trace of callstack:
';
array_shift($dbt);
foreach($dbt as $eachCall)
{
echo $eachCall['function'].' called from '.$eachCall['file'].':';
echo $eachCall['line'].'
';
}
echo '';
}//}}}end function _printStackTrace
}
if (!function_exists('debug_backtrace'))
{
function debug_backtrace( )
{
$arr = array('function' => __FUNCTION__,
'line' => __LINE__,
'file' => __FILE__,
'class' => __CLASS__,
'type' => 'Undefined',
'args' => 'Undefined');
return array($arr, $arr);
}
}
?>