* @license PHP License
* @package wb
* @subpackage Markup
*/
WBClass::load('WBMarkup_Handler');
/**
* Markup Scanner Handler: Xml2Xinha
*
* Convert Wombat XML data to Xinha-HTML with Wombat attributes
*
* @version 0.2.0
* @package wb
* @subpackage Markup
*/
class WBMarkup_Handler_Xml2Xinha implements WBMarkup_Handler
{
/**
* current depth
* @var int
*/
protected $depth = 0;
/**
* content
* @var string
*/
protected $content = '';
/**
* document's md5 sum
* @var string
*/
protected $md5;
/**
* document nodes
* @var array
*/
protected $doc = array();
/**
* list of running converters (WBMarkup_Converter)
* @var array
*/
protected $con = array();
/**
* handler on start beginning of scan
*
*
*
* @param string $content
* @return bool usually true, false to stop the scanner
*/
public function onScanStart(&$content)
{
$this->con = array();
$this->depth = 0;
$this->content =& $content;
$this->md5 = md5($content);
$this->doc = array();
$this->doc[0] = array(
'ns' => '',
'tag' => '',
'attributes' => array(),
'isEmpty' => false,
'cData' => array(),
'depth' => $this->depth
);
// inform converter about document's md5 and content
foreach (array_keys($this->con) as $con) {
$this->con[$con]->preset($this, $content);
}
return true;
}
/**
* handler on start element
*
* @param string $ns The used namespace, if set. otherwise null
* @param string $tag the tag itself
* @param array $attributes the attributes of the found element
* @param bool $isEmpty true if it is a start- and closing-Element (e.g.
)
* @return bool usually true, false to stop the scanner
*/
public function onStartElement($ns, $tag, $attributes, $isEmpty)
{
++$this->depth;
$this->doc[$this->depth] = array(
'ns' => $ns,
'tag' => $tag,
'attributes' => $attributes,
'isEmpty' => $isEmpty,
'cData' => array(),
'depth' => $this->depth
);
return true;
}
/**
* handler fo cData
*
* Simply add cDate to document
*
* @uses replaceUrlString()
* @param string $cData character data
* @return bool usually true, false to stop the scanner
*/
public function onCharacterData($cData)
{
$this->doc[$this->depth]['cData'][] = $cData;
return true;
}
/**
* handler for entities
*
* Add entities to document's cData
*
* @param string $entity the entity element, e.g. nbsp for
* @param boolean $isUnicode true = the element is a unicode string
*/
public function onEntityElement($entity, $isUnicode)
{
$cData = '&';
if( $isUnicode ) {
$cData .= '#';
}
$cData .= $entity . ';';
$this->doc[$this->depth]['cData'][] = $cData;
return true;
}
/**
* test handler on end element
*
* @param string $ns The used namespace, if set. otherwise null
* @param string $tag the tag itself
* @param bool $empty defines if the tag is empty
* @return bool usually true, false to stop the scanner
*/
public function onEndElement($ns, $tag, $empty)
{
// serialize node
if( !$this->depth ) {
return true;
}
$node = array_pop($this->doc);
if ($node['ns']) {
$this->convert($node['ns'], $node['tag'], $node);
}
--$this->depth;
if( $this->depth < 0 ) {
$this->depth = 0;
}
$this->doc[$this->depth]['cData'][] = $this->node2String($node);
return true;
}
/**
* called right after scan is complete
*
* @return bool usually true, false to stop the scanner
*/
public function onScanComplete()
{
$this->content = $this->node2String($this->doc[0]);
// inform converter
foreach (array_keys($this->con) as $con) {
$this->con[$con]->reset();
}
// flush listener
$this->listener = array();
return true;
}
/**
* receive translated content string
*
* @return string
*/
public function getParsedContent()
{
return $this->content;
}
/**
* convert node
*
* transform namespaced tags to HTML
*
* @todo convert empty namespace (standard HTML) to known WB namespace, if possible
* @param string $ns
* @param string $tag
* @param array $node
*/
protected function convert($ns, $tag, &$node)
{
$con = $this->getConverter($ns, $tag);
if (!$con) {
return '';
}
return $con->toXinha($node);
}
/**
* cet instance of matching converter
*
* See whether convert is already running, start it otherwise
*
* @param $ns
* @param $tag
* @return WBMarkup_Converter
*/
protected function getConverter($ns, $tag)
{
$con = ucfirst(strtolower($ns))
. '_'
. ucfirst(strtolower($tag));
try{
if (!isset($this->con[$con])) {
$this->con[$con] = WBClass::create('WBMarkup_Converter_' . $con);
/** @var $this->con[$con] WBMarkup_Converter */
$this->con[$con]->preset($this, $this->content);
}
} catch(WBException_Class $e) {
return null;
}
return $this->con[$con];
}
/**
* serialize document node
*
* @param array $node
* @return string serialized attributes
*/
protected function node2String($node)
{
$cData = implode('', $node['cData']);
if (!$node['tag']) {
return $cData;
}
$tag = '';
if ($node['ns']) {
$tag .= $node['ns'] . ':';
}
$tag .= $node['tag'];
$element = '<' . $tag . $this->attributes2String($node['attributes']);
if ($node['isEmpty']) {
$element .= ' />';
return $element;
}
$element .= '>' . $cData . '' . $tag . '>';
return $element;
}
/**
* serialize attribute list to HTML attribute string
*
* @param array $att attribute list
* @return string serialized attributes
*/
protected function attributes2String($att)
{
if (empty($att)) {
return '';
}
$str = '';
foreach ($att as $k => $v) {
$str .= ' ' . $k . '="' . $v . '"';
}
return $str;
}
}
?>