Subversion Repositories Applications.papyrus

Compare Revisions

Ignore whitespace Rev 340 → Rev 341

/trunk/api/pear/XML/Tree/Node.php
New file
0,0 → 1,354
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Bernd Römer <berndr@bonn.edu> |
// | Sebastian Bergmann <sb@sebastian-bergmann.de> |
// | Christian Kühn <ck@chkuehn.de> (escape xml entities) |
// +----------------------------------------------------------------------+
//
// $Id: Node.php,v 1.1 2005-04-18 16:13:31 jpm Exp $
//
 
/**
* PEAR::XML_Tree_Node
*
* @author Bernd Römer <berndr@bonn.edu>
* @package XML_Tree
* @version 1.0 16-Aug-2001
*/
class XML_Tree_Node {
/**
* Attributes of this node
*
* @var array
*/
var $attributes;
 
/**
* Children of this node
*
* @var array
*/
var $children;
 
/**
* Content
*
* @var string
*/
var $content;
 
/**
* Name
*
* @var string
*/
var $name;
 
/**
* Constructor
*
* @param string name
* @param string content
* @param array attributes
*/
function XML_Tree_Node($name, $content = '', $attributes = array()) {
$this->attributes = $attributes;
$this->children = array();
$this->set_content($content);
$this->name = $name;
}
 
/**
* Adds a child node to this node.
*
* @param mixed child
* @param string content
* @param array attributes
* @return object reference to new child node
*/
function &addChild($child, $content = '', $attributes = array()) {
$index = sizeof($this->children);
 
if (is_object($child)) {
if (strtolower(get_class($child)) == 'xml_tree_node') {
$this->children[$index] = $child;
}
 
if (strtolower(get_class($child)) == 'xml_tree' && isset($child->root)) {
$this->children[$index] = $child->root->get_element();
}
} else {
$this->children[$index] = new XML_Tree_Node($child, $content, $attributes);
}
 
return $this->children[$index];
}
 
/**
* @deprecated
*/
function &add_child($child, $content = '', $attributes = array()) {
return $this->addChild($child, $content, $attributes);
}
 
/**
* clone node and all its children (recursive)
*
* @return object reference to the clone-node
*/
function &clone() {
$clone=new XML_Tree_Node($this->name,$this->content,$this->attributes);
 
$max_child=count($this->children);
for($i=0;$i<$max_child;$i++) {
$clone->children[]=$this->children[$i]->clone();
}
 
/* for future use....
// clone all other vars
$temp=get_object_vars($this);
foreach($temp as $varname => $value)
if (!in_array($varname,array('name','content','attributes','children')))
$clone->$varname=$value;
*/
 
return($clone);
}
 
/**
* inserts child ($child) to a specified child-position ($pos)
*
* @return inserted node
*/
function &insertChild($path,$pos,&$child, $content = '', $attributes = array()) {
// direct insert of objects useing array_splice() faild :(
array_splice($this->children,$pos,0,'dummy');
if (is_object($child)) { // child offered is not instanziated
// insert a single node
if (strtolower(get_class($child)) == 'xml_tree_node') {
$this->children[$pos]=&$child;
}
// insert a tree i.e insert root-element
if (strtolower(get_class($child)) == 'xml_tree' && isset($child->root)) {
$this->children[$pos]=$child->root->get_element();
}
} else { // child offered is not instanziated
$this->children[$pos]=new XML_Tree_Node($child, $content, $attributes);
}
return($this);
}
 
/**
* @deprecated
*/
function &insert_child($path,$pos,&$child, $content = '', $attributes = array()) {
return $this->insertChild($path,$pos,$child, $content, $attributes);
}
 
/**
* removes child ($pos)
*
* @param integer pos position of child in children-list
*
* @return removed node
*/
function &removeChild($pos) {
// array_splice() instead of a simple unset() to maintain index-integrity
return(array_splice($this->children,$pos,1));
}
 
/**
* @deprecated
*/
function &remove_child($pos) {
return $this->removeChild($pos);
}
 
/**
* Returns text representation of this node.
*
* @return string xml
*/
function &get()
{
static $deep = -1;
static $do_ident = true;
$deep++;
if ($this->name !== null) {
$ident = str_repeat(' ', $deep);
if ($do_ident) {
$out = $ident . '<' . $this->name;
} else {
$out = '<' . $this->name;
}
foreach ($this->attributes as $name => $value) {
$out .= ' ' . $name . '="' . $value . '"';
}
 
$out .= '>' . $this->content;
 
if (sizeof($this->children) > 0) {
$out .= "\n";
foreach ($this->children as $child) {
$out .= $child->get();
}
} else {
$ident = '';
}
if ($do_ident) {
$out .= $ident . '</' . $this->name . ">\n";
} else {
$out .= '</' . $this->name . '>';
}
$do_ident = true;
} else {
$out = $this->content;
$do_ident = false;
}
$deep--;
return $out;
}
 
/**
* Gets an attribute by its name.
*
* @param string name
* @return string attribute
*/
function getAttribute($name) {
return $this->attributes[strtolower($name)];
}
 
/**
* @deprecated
*/
function get_attribute($name) {
return $this->getAttribute($name);
}
 
/**
* Gets an element by its 'path'.
*
* @param string path
* @return object element
*/
function &getElement($path) {
if (sizeof($path) == 0) {
return $this;
}
 
$next = array_shift($path);
 
return $this->children[$next]->get_element($path);
}
 
/**
* @deprecated
*/
function &get_element($path) {
return $this->getElement($path);
}
 
/**
* Sets an attribute.
*
* @param string name
* @param string value
*/
function setAttribute($name, $value = '') {
$this->attributes[strtolower($name)] = $value;
}
 
/**
* @deprecated
*/
function set_attribute($name, $value = '') {
return $this->setAttribute($name, $value);
}
 
/**
* Unsets an attribute.
*
* @param string name
*/
function unsetAttribute($name) {
unset($this->attributes[strtolower($name)]);
}
 
/**
* @deprecated
*/
function unset_attribute($name) {
return $this->unsetAttribute($name);
}
 
/**
*
*
*/
function setContent(&$content)
{
$this->content = $this->_xml_entities($content);
}
 
function set_content(&$content)
{
return $this->setContent($content);
}
 
/**
* Escape XML entities.
*
* @param string xml
* @return string xml
* @access private
*/
function _xml_entities($xml) {
$xml = str_replace(array('ü', 'Ü', 'ö',
'Ö', 'ä', 'Ä',
'ß'
),
array('&#252;', '&#220;', '&#246;',
'&#214;', '&#228;', '&#196;',
'&#223;'
),
$xml
);
 
$xml = preg_replace(array("/\&([a-z\d\#]+)\;/i",
"/\&/",
"/\#\|\|([a-z\d\#]+)\|\|\#/i",
"/([^a-zA-Z\d\s\<\>\&\;\.\:\=\"\-\/\%\?\!\'\(\)\[\]\{\}\$\#\+\,\@_])/e"
),
array("#||\\1||#",
"&amp;",
"&\\1;",
"'&#'.ord('\\1').';'"
),
$xml
);
 
return $xml;
}
 
/**
* Print text representation of XML tree.
*/
function dump() {
echo $this->get();
}
}
?>
/trunk/api/pear/XML/Parser.php
New file
0,0 → 1,684
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/3_0.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Stig Bakken <ssb@fast.no> |
// | Tomas V.V.Cox <cox@idecnet.com> |
// | Stephan Schmidt <schst@php-tools.net> |
// +----------------------------------------------------------------------+
//
// $Id: Parser.php,v 1.1 2005-04-18 16:13:31 jpm Exp $
 
/**
* XML Parser class.
*
* This is an XML parser based on PHP's "xml" extension,
* based on the bundled expat library.
*
* @category XML
* @package XML_Parser
* @author Stig Bakken <ssb@fast.no>
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Stephan Schmidt <schst@php-tools.net>
*/
 
/**
* uses PEAR's error handling
*/
require_once 'PEAR.php';
 
/**
* resource could not be created
*/
define('XML_PARSER_ERROR_NO_RESOURCE', 200);
 
/**
* unsupported mode
*/
define('XML_PARSER_ERROR_UNSUPPORTED_MODE', 201);
 
/**
* invalid encoding was given
*/
define('XML_PARSER_ERROR_INVALID_ENCODING', 202);
 
/**
* specified file could not be read
*/
define('XML_PARSER_ERROR_FILE_NOT_READABLE', 203);
 
/**
* invalid input
*/
define('XML_PARSER_ERROR_INVALID_INPUT', 204);
 
/**
* remote file cannot be retrieved in safe mode
*/
define('XML_PARSER_ERROR_REMOTE', 205);
 
/**
* XML Parser class.
*
* This is an XML parser based on PHP's "xml" extension,
* based on the bundled expat library.
*
* Notes:
* - It requires PHP 4.0.4pl1 or greater
* - From revision 1.17, the function names used by the 'func' mode
* are in the format "xmltag_$elem", for example: use "xmltag_name"
* to handle the <name></name> tags of your xml file.
*
* @category XML
* @package XML_Parser
* @author Stig Bakken <ssb@fast.no>
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Stephan Schmidt <schst@php-tools.net>
* @todo create XML_Parser_Namespace to parse documents with namespaces
* @todo create XML_Parser_Pull
* @todo Tests that need to be made:
* - mixing character encodings
* - a test using all expat handlers
* - options (folding, output charset)
* - different parsing modes
*/
class XML_Parser extends PEAR
{
// {{{ properties
 
/**
* XML parser handle
*
* @var resource
* @see xml_parser_create()
*/
var $parser;
 
/**
* File handle if parsing from a file
*
* @var resource
*/
var $fp;
 
/**
* Whether to do case folding
*
* If set to true, all tag and attribute names will
* be converted to UPPER CASE.
*
* @var boolean
*/
var $folding = true;
 
/**
* Mode of operation, one of "event" or "func"
*
* @var string
*/
var $mode;
 
/**
* Mapping from expat handler function to class method.
*
* @var array
*/
var $handler = array(
'character_data_handler' => 'cdataHandler',
'default_handler' => 'defaultHandler',
'processing_instruction_handler' => 'piHandler',
'unparsed_entity_decl_handler' => 'unparsedHandler',
'notation_decl_handler' => 'notationHandler',
'external_entity_ref_handler' => 'entityrefHandler'
);
 
/**
* source encoding
*
* @var string
*/
var $srcenc;
 
/**
* target encoding
*
* @var string
*/
var $tgtenc;
 
/**
* handler object
*
* @var object
*/
var $_handlerObj;
 
// }}}
// {{{ constructor
 
/**
* Creates an XML parser.
*
* This is needed for PHP4 compatibility, it will
* call the constructor, when a new instance is created.
*
* @param string $srcenc source charset encoding, use NULL (default) to use
* whatever the document specifies
* @param string $mode how this parser object should work, "event" for
* startelement/endelement-type events, "func"
* to have it call functions named after elements
* @param string $tgenc a valid target encoding
*/
function XML_Parser($srcenc = null, $mode = 'event', $tgtenc = null)
{
XML_Parser::__construct($srcenc, $mode, $tgtenc);
}
// }}}
 
/**
* PHP5 constructor
*
* @param string $srcenc source charset encoding, use NULL (default) to use
* whatever the document specifies
* @param string $mode how this parser object should work, "event" for
* startelement/endelement-type events, "func"
* to have it call functions named after elements
* @param string $tgenc a valid target encoding
*/
function __construct($srcenc = null, $mode = 'event', $tgtenc = null)
{
$this->PEAR('XML_Parser_Error');
 
$this->mode = $mode;
$this->srcenc = $srcenc;
$this->tgtenc = $tgtenc;
}
// }}}
 
/**
* Sets the mode of the parser.
*
* Possible modes are:
* - func
* - event
*
* You can set the mode using the second parameter
* in the constructor.
*
* This method is only needed, when switching to a new
* mode at a later point.
*
* @access public
* @param string mode, either 'func' or 'event'
* @return boolean|object true on success, PEAR_Error otherwise
*/
function setMode($mode)
{
if ($mode != 'func' && $mode != 'event') {
$this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE);
}
 
$this->mode = $mode;
return true;
}
 
/**
* Sets the object, that will handle the XML events
*
* This allows you to create a handler object independent of the
* parser object that you are using and easily switch the underlying
* parser.
*
* If no object will be set, XML_Parser assumes that you
* extend this class and handle the events in $this.
*
* @access public
* @param object object to handle the events
* @return boolean will always return true
* @since v1.2.0beta3
*/
function setHandlerObj(&$obj)
{
$this->_handlerObj = &$obj;
return true;
}
 
/**
* Init the element handlers
*
* @access private
*/
function _initHandlers()
{
if (!is_resource($this->parser)) {
return false;
}
 
if (!is_object($this->_handlerObj)) {
$this->_handlerObj = &$this;
}
switch ($this->mode) {
 
case 'func':
xml_set_object($this->parser, $this->_handlerObj);
xml_set_element_handler($this->parser, array(&$this, 'funcStartHandler'), array(&$this, 'funcEndHandler'));
break;
 
case 'event':
xml_set_object($this->parser, $this->_handlerObj);
xml_set_element_handler($this->parser, 'startHandler', 'endHandler');
break;
default:
return $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE);
break;
}
 
 
/**
* set additional handlers for character data, entities, etc.
*/
foreach ($this->handler as $xml_func => $method) {
if (method_exists($this->_handlerObj, $method)) {
$xml_func = 'xml_set_' . $xml_func;
$xml_func($this->parser, $method);
}
}
}
 
// {{{ _create()
 
/**
* create the XML parser resource
*
* Has been moved from the constructor to avoid
* problems with object references.
*
* Furthermore it allows us returning an error
* if something fails.
*
* @access private
* @return boolean|object true on success, PEAR_Error otherwise
*
* @see xml_parser_create
*/
function _create()
{
if ($this->srcenc === null) {
$xp = @xml_parser_create();
} else {
$xp = @xml_parser_create($this->srcenc);
}
if (is_resource($xp)) {
if ($this->tgtenc !== null) {
if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING,
$this->tgtenc)) {
return $this->raiseError('invalid target encoding', XML_PARSER_ERROR_INVALID_ENCODING);
}
}
$this->parser = $xp;
$result = $this->_initHandlers($this->mode);
if ($this->isError($result)) {
return $result;
}
xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, $this->folding);
 
return true;
}
return $this->raiseError('Unable to create XML parser resource.', XML_PARSER_ERROR_NO_RESOURCE);
}
 
// }}}
// {{{ reset()
 
/**
* Reset the parser.
*
* This allows you to use one parser instance
* to parse multiple XML documents.
*
* @access public
* @return boolean|object true on success, PEAR_Error otherwise
*/
function reset()
{
$result = $this->_create();
if ($this->isError( $result )) {
return $result;
}
return true;
}
 
// }}}
// {{{ setInputFile()
 
/**
* Sets the input xml file to be parsed
*
* @param string Filename (full path)
* @return resource fopen handle of the given file
* @throws XML_Parser_Error
* @see setInput(), setInputString(), parse()
* @access public
*/
function setInputFile($file)
{
/**
* check, if file is a remote file
*/
if (eregi('^(http|ftp)://', substr($file, 0, 10))) {
if (!ini_get('allow_url_fopen')) {
return $this->raiseError('Remote files cannot be parsed, as safe mode is enabled.', XML_PARSER_ERROR_REMOTE);
}
}
$fp = @fopen($file, 'rb');
if (is_resource($fp)) {
$this->fp = $fp;
return $fp;
}
return $this->raiseError('File could not be opened.', XML_PARSER_ERROR_FILE_NOT_READABLE);
}
 
// }}}
// {{{ setInputString()
/**
* XML_Parser::setInputString()
*
* Sets the xml input from a string
*
* @param string $data a string containing the XML document
* @return null
**/
function setInputString($data)
{
$this->fp = $data;
return null;
}
// }}}
// {{{ setInput()
 
/**
* Sets the file handle to use with parse().
*
* You should use setInputFile() or setInputString() if you
* pass a string
*
* @param mixed $fp Can be either a resource returned from fopen(),
* a URL, a local filename or a string.
* @access public
* @see parse()
* @uses setInputString(), setInputFile()
*/
function setInput($fp)
{
if (is_resource($fp)) {
$this->fp = $fp;
return true;
}
// see if it's an absolute URL (has a scheme at the beginning)
elseif (eregi('^[a-z]+://', substr($fp, 0, 10))) {
return $this->setInputFile($fp);
}
// see if it's a local file
elseif (file_exists($fp)) {
return $this->setInputFile($fp);
}
// it must be a string
else {
$this->fp = $fp;
return true;
}
 
return $this->raiseError('Illegal input format', XML_PARSER_ERROR_INVALID_INPUT);
}
 
// }}}
// {{{ parse()
 
/**
* Central parsing function.
*
* @return true|object PEAR error returns true on success, or a PEAR_Error otherwise
* @access public
*/
function parse()
{
/**
* reset the parser
*/
$result = $this->reset();
if ($this->isError($result)) {
return $result;
}
// if $this->fp was fopened previously
if (is_resource($this->fp)) {
while ($data = fread($this->fp, 4096)) {
if (!$this->_parseString($data, feof($this->fp))) {
$error = &$this->raiseError();
$this->free();
return $error;
}
}
// otherwise, $this->fp must be a string
} else {
if (!$this->_parseString($this->fp, true)) {
$error = &$this->raiseError();
$this->free();
return $error;
}
}
$this->free();
 
return true;
}
 
/**
* XML_Parser::_parseString()
*
* @param string $data
* @param boolean $eof
* @return bool
* @access private
* @see parseString()
**/
function _parseString($data, $eof = false)
{
return xml_parse($this->parser, $data, $eof);
}
// }}}
// {{{ parseString()
 
/**
* XML_Parser::parseString()
*
* Parses a string.
*
* @param string $data XML data
* @param boolean $eof If set and TRUE, data is the last piece of data sent in this parser
* @throws XML_Parser_Error
* @return Pear Error|true true on success or a PEAR Error
* @see _parseString()
*/
function parseString($data, $eof = false)
{
if (!isset($this->parser) || !is_resource($this->parser)) {
$this->reset();
}
if (!$this->_parseString($data, $eof)) {
$error = &$this->raiseError();
$this->free();
return $error;
}
 
if ($eof === true) {
$this->free();
}
return true;
}
/**
* XML_Parser::free()
*
* Free the internal resources associated with the parser
*
* @return null
**/
function free()
{
if (isset($this->parser) && is_resource($this->parser)) {
xml_parser_free($this->parser);
unset( $this->parser );
}
if (isset($this->fp) && is_resource($this->fp)) {
fclose($this->fp);
}
unset($this->fp);
return null;
}
/**
* XML_Parser::raiseError()
*
* Throws a XML_Parser_Error
*
* @param string $msg the error message
* @param integer $ecode the error message code
* @return XML_Parser_Error
**/
function raiseError($msg = null, $ecode = 0)
{
$msg = !is_null($msg) ? $msg : $this->parser;
$err = &new XML_Parser_Error($msg, $ecode);
return parent::raiseError($err);
}
// }}}
// {{{ funcStartHandler()
 
function funcStartHandler($xp, $elem, $attribs)
{
$func = 'xmltag_' . $elem;
if (strchr($func, '.')) {
$func = str_replace('.', '_', $func);
}
if (method_exists($this->_handlerObj, $func)) {
call_user_func(array(&$this->_handlerObj, $func), $xp, $elem, $attribs);
} elseif (method_exists($this->_handlerObj, 'xmltag')) {
call_user_func(array(&$this->_handlerObj, 'xmltag'), $xp, $elem, $attribs);
}
}
 
// }}}
// {{{ funcEndHandler()
 
function funcEndHandler($xp, $elem)
{
$func = 'xmltag_' . $elem . '_';
if (strchr($func, '.')) {
$func = str_replace('.', '_', $func);
}
if (method_exists($this->_handlerObj, $func)) {
call_user_func(array(&$this->_handlerObj, $func), $xp, $elem);
} elseif (method_exists($this->_handlerObj, 'xmltag_')) {
call_user_func(array(&$this->_handlerObj, 'xmltag_'), $xp, $elem);
}
}
 
// }}}
// {{{ startHandler()
 
/**
*
* @abstract
*/
function startHandler($xp, $elem, &$attribs)
{
return NULL;
}
 
// }}}
// {{{ endHandler()
 
/**
*
* @abstract
*/
function endHandler($xp, $elem)
{
return NULL;
}
 
 
// }}}me
}
 
/**
* error class, replaces PEAR_Error
*
* An instance of this class will be returned
* if an error occurs inside XML_Parser.
*
* There are three advantages over using the standard PEAR_Error:
* - All messages will be prefixed
* - check for XML_Parser error, using is_a( $error, 'XML_Parser_Error' )
* - messages can be generated from the xml_parser resource
*
* @package XML_Parser
* @access public
* @see PEAR_Error
*/
class XML_Parser_Error extends PEAR_Error
{
// {{{ properties
 
/**
* prefix for all messages
*
* @var string
*/
var $error_message_prefix = 'XML_Parser: ';
 
// }}}
// {{{ constructor()
/**
* construct a new error instance
*
* You may either pass a message or an xml_parser resource as first
* parameter. If a resource has been passed, the last error that
* happened will be retrieved and returned.
*
* @access public
* @param string|resource message or parser resource
* @param integer error code
* @param integer error handling
* @param integer error level
*/
function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE)
{
if (is_resource($msgorparser)) {
$code = xml_get_error_code($msgorparser);
$msgorparser = sprintf('%s at XML input line %d',
xml_error_string($code),
xml_get_current_line_number($msgorparser));
}
$this->PEAR_Error($msgorparser, $code, $mode, $level);
}
// }}}
}
?>
/trunk/api/pear/XML/Tree.php
New file
0,0 → 1,370
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Bernd Römer <berndr@bonn.edu> |
// | Sebastian Bergmann <sb@sebastian-bergmann.de> |
// | Tomas V.V.Cox <cox@idecnet.com> (tree mapping from xml file)|
// +----------------------------------------------------------------------+
//
// $Id: Tree.php,v 1.1 2005-04-18 16:13:31 jpm Exp $
//
 
require_once 'XML/Parser.php';
require_once 'XML/Tree/Node.php';
 
/**
* PEAR::XML_Tree
*
* Purpose
*
* Allows for the building of XML data structures
* using a tree representation, without the need
* for an extension like DOMXML.
*
* Example
*
* $tree = new XML_Tree;
* $root =& $tree->addRoot('root');
* $foo =& $root->addChild('foo');
*
* header('Content-Type: text/xml');
* $tree->dump();
*
* @author Bernd Römer <berndr@bonn.edu>
* @package XML
* @version $Version$ - 1.0
*/
class XML_Tree extends XML_Parser
{
/**
* File Handle
*
* @var ressource
*/
var $file = NULL;
 
/**
* Filename
*
* @var string
*/
var $filename = '';
 
/**
* Namespace
*
* @var array
*/
var $namespace = array();
 
/**
* Root
*
* @var object XML_Tree_Node
*/
var $root = NULL;
 
/**
* XML Version
*
* @var string
*/
var $version = '1.0';
 
/**
* Constructor
*
* @param string Filename
* @param string XML Version
*/
function XML_Tree($filename = '', $version = '1.0') {
$this->filename = $filename;
$this->version = $version;
}
 
/**
* Add root node.
*
* @param string $name name of root element
* @return object XML_Tree_Node reference to root node
*
* @access public
*/
function &addRoot($name, $content = '', $attributes = array()) {
$this->root = new XML_Tree_Node($name, $content, $attributes);
return $this->root;
}
 
/**
* @deprecated
*/
function &add_root($name, $content = '', $attributes = array()) {
return $this->addRoot($name, $content, $attributes);
}
 
/**
* inserts a child/tree (child) into tree ($path,$pos) and
* maintains namespace integrity
*
* @param array $path path to parent of child to remove
* @param integer $pos position of child to be inserted in its parents children-list
* @param mixed $child child-node (by XML_Tree,XML_Node or Name)
* @param string $content content (text) for new node
* @param array $attributes attribute-hash for new node
*
* @return object XML_Tree_Node inserted child (node)
* @access public
*/
function &insertChild($path,$pos,$child, $content = '', $attributes = array()) {
// update namespace to maintain namespace integrity
$count=count($path);
foreach($this->namespace as $key => $val) {
if ((array_slice($val,0,$count)==$path) && ($val[$count]>=$pos))
$this->namespace[$key][$count]++;
}
 
$parent=&$this->get_node_by_path($path);
return($parent->insert_child($pos,$child,$content,$attributes));
}
 
/**
* @deprecated
*/
function &insert_child($path,$pos,$child, $content = '', $attributes = array()) {
return $this->insertChild($path, $child, $content, $attributes);
}
 
/*
* removes a child ($path,$pos) from tree ($path,$pos) and
* maintains namespace integrity
*
* @param array $path path to parent of child to remove
* @param integer $pos position of child in parents children-list
*
* @return object XML_Tree_Node parent whichs child was removed
* @access public
*/
function &removeChild($path,$pos) {
// update namespace to maintain namespace integrity
$count=count($path);
foreach($this->namespace as $key => $val) {
if (array_slice($val,0,$count)==$path) {
if ($val[$count]==$pos) { unset($this->namespace[$key]); break; }
if ($val[$count]>$pos)
$this->namespace[$key][$count]--;
}
}
 
$parent=&$this->get_node_by_path($path);
return($parent->remove_child($pos));
}
 
/**
* @deprecated
*/
function &remove_child($path, $pos) {
return $this->removeChild($path, $pos);
}
 
/*
* Maps a xml file to a objects tree
*
* @return mixed The objects tree (XML_tree or an Pear error)
* @access public
*/
function &getTreeFromFile ()
{
$this->folding = false;
$this->XML_Parser(null, 'event');
$err = $this->setInputFile($this->filename);
if (PEAR::isError($err)) {
return $err;
}
$this->cdata = null;
$err = $this->parse();
if (PEAR::isError($err)) {
return $err;
}
return $this->root;
}
 
function getTreeFromString($str)
{
$this->folding = false;
$this->XML_Parser(null, 'event');
$this->cdata = null;
$err = $this->parseString($str);
if (PEAR::isError($err)) {
return $err;
}
return $this->root;
}
 
/**
* Handler for the xml-data
*
* @param mixed $xp ignored
* @param string $elem name of the element
* @param array $attribs attributes for the generated node
*
* @access private
*/
function startHandler($xp, $elem, &$attribs)
{
// root elem
if (!isset($this->i)) {
$this->obj1 =& $this->add_root($elem, null, $attribs);
$this->i = 2;
} else {
// mixed contents
if (!empty($this->cdata)) {
$parent_id = 'obj' . ($this->i - 1);
$parent =& $this->$parent_id;
$parent->children[] = &new XML_Tree_Node(null, $this->cdata);
}
$obj_id = 'obj' . $this->i++;
$this->$obj_id = &new XML_Tree_Node($elem, null, $attribs);
}
$this->cdata = null;
return null;
}
 
/**
* Handler for the xml-data
*
* @param mixed $xp ignored
* @param string $elem name of the element
*
* @access private
*/
function endHandler($xp, $elem)
{
$this->i--;
if ($this->i > 1) {
$obj_id = 'obj' . $this->i;
// recover the node created in StartHandler
$node =& $this->$obj_id;
// mixed contents
if (count($node->children) > 0) {
if (trim($this->cdata)) {
$node->children[] = &new XML_Tree_Node(null, $this->cdata);
}
} else {
$node->set_content($this->cdata);
}
$parent_id = 'obj' . ($this->i - 1);
$parent =& $this->$parent_id;
// attach the node to its parent node children array
$parent->children[] = $node;
}
$this->cdata = null;
return null;
}
 
/*
* The xml character data handler
*
* @param mixed $xp ignored
* @param string $data PCDATA between tags
*
* @access private
*/
function cdataHandler($xp, $data)
{
if (trim($data)) {
$this->cdata .= $data;
}
}
 
/**
* Get a copy of this tree.
*
* @return object XML_Tree
* @access public
*/
function clone() {
$clone=new XML_Tree($this->filename,$this->version);
$clone->root=$this->root->clone();
 
// clone all other vars
$temp=get_object_vars($this);
foreach($temp as $varname => $value)
if (!in_array($varname,array('filename','version','root')))
$clone->$varname=$value;
 
return($clone);
}
 
/**
* Print text representation of XML tree.
*
* @access public
*/
function dump() {
echo $this->get();
}
 
/**
* Get text representation of XML tree.
*
* @return string XML
* @access public
*/
function &get() {
$out = '<?xml version="' . $this->version . "\"?>\n";
$out .= $this->root->get();
 
return $out;
}
 
/**
* Get current namespace.
*
* @param string $name namespace
* @return string
*
* @access public
*/
function &getName($name) {
return $this->root->get_element($this->namespace[$name]);
}
 
/**
* @deprecated
*/
function &get_name($name) {
return $this->getName($name);
}
 
/**
* Register a namespace.
*
* @param string $name namespace
* @param string $path path
*
* @access public
*/
function registerName($name, $path) {
$this->namespace[$name] = $path;
}
 
/**
* @deprecated
*/
function register_name($name, $path) {
return $this->registerName($name, $path);
}
}
?>
/trunk/api/pear/XML/Parser/Simple.php
New file
0,0 → 1,297
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/3_0.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Stephan Schmidt <schst@php-tools.net> |
// +----------------------------------------------------------------------+
//
// $Id: Simple.php,v 1.1 2005-04-18 16:13:31 jpm Exp $
 
/**
* Simple XML parser class.
*
* This class is a simplified version of XML_Parser.
* In most XML applications the real action is executed,
* when a closing tag is found.
*
* XML_Parser_Simple allows you to just implement one callback
* for each tag that will receive the tag with its attributes
* and CData
*
* @category XML
* @package XML_Parser
* @author Stephan Schmidt <schst@php-tools.net>
*/
 
/**
* built on XML_Parser
*/
require_once 'XML/Parser.php';
 
/**
* Simple XML parser class.
*
* This class is a simplified version of XML_Parser.
* In most XML applications the real action is executed,
* when a closing tag is found.
*
* XML_Parser_Simple allows you to just implement one callback
* for each tag that will receive the tag with its attributes
* and CData.
*
* <code>
* require_once '../Parser/Simple.php';
*
* class myParser extends XML_Parser_Simple
* {
* function myParser()
* {
* $this->XML_Parser_Simple();
* }
*
* function handleElement($name, $attribs, $data)
* {
* printf('handle %s<br>', $name);
* }
* }
*
* $p = &new myParser();
*
* $result = $p->setInputFile('myDoc.xml');
* $result = $p->parse();
* </code>
*
* @category XML
* @package XML_Parser
* @author Stephan Schmidt <schst@php-tools.net>
*/
class XML_Parser_Simple extends XML_Parser
{
/**
* element stack
*
* @access private
* @var array
*/
var $_elStack = array();
 
/**
* all character data
*
* @access private
* @var array
*/
var $_data = array();
 
/**
* element depth
*
* @access private
* @var integer
*/
var $_depth = 0;
 
/**
* Mapping from expat handler function to class method.
*
* @var array
*/
var $handler = array(
'default_handler' => 'defaultHandler',
'processing_instruction_handler' => 'piHandler',
'unparsed_entity_decl_handler' => 'unparsedHandler',
'notation_decl_handler' => 'notationHandler',
'external_entity_ref_handler' => 'entityrefHandler'
);
/**
* Creates an XML parser.
*
* This is needed for PHP4 compatibility, it will
* call the constructor, when a new instance is created.
*
* @param string $srcenc source charset encoding, use NULL (default) to use
* whatever the document specifies
* @param string $mode how this parser object should work, "event" for
* handleElement(), "func" to have it call functions
* named after elements (handleElement_$name())
* @param string $tgenc a valid target encoding
*/
function XML_Parser_Simple($srcenc = null, $mode = 'event', $tgtenc = null)
{
$this->XML_Parser($srcenc, $mode, $tgtenc);
}
 
/**
* inits the handlers
*
* @access private
*/
function _initHandlers()
{
if (!is_object($this->_handlerObj)) {
$this->_handlerObj = &$this;
}
 
if ($this->mode != 'func' && $this->mode != 'event') {
return $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE);
}
xml_set_object($this->parser, $this->_handlerObj);
 
xml_set_element_handler($this->parser, array(&$this, 'startHandler'), array(&$this, 'endHandler'));
xml_set_character_data_handler($this->parser, array(&$this, 'cdataHandler'));
/**
* set additional handlers for character data, entities, etc.
*/
foreach ($this->handler as $xml_func => $method) {
if (method_exists($this->_handlerObj, $method)) {
$xml_func = 'xml_set_' . $xml_func;
$xml_func($this->parser, $method);
}
}
}
 
/**
* Reset the parser.
*
* This allows you to use one parser instance
* to parse multiple XML documents.
*
* @access public
* @return boolean|object true on success, PEAR_Error otherwise
*/
function reset()
{
$this->_elStack = array();
$this->_data = array();
$this->_depth = 0;
$result = $this->_create();
if ($this->isError( $result )) {
return $result;
}
return true;
}
 
/**
* start handler
*
* Pushes attributes and tagname onto a stack
*
* @access private
* @final
* @param resource xml parser resource
* @param string element name
* @param array attributes
*/
function startHandler($xp, $elem, &$attribs)
{
array_push($this->_elStack, array(
'name' => $elem,
'attribs' => $attribs
)
);
$this->_depth++;
$this->_data[$this->_depth] = '';
}
 
/**
* end handler
*
* Pulls attributes and tagname from a stack
*
* @access private
* @final
* @param resource xml parser resource
* @param string element name
*/
function endHandler($xp, $elem)
{
$el = array_pop($this->_elStack);
$data = $this->_data[$this->_depth];
$this->_depth--;
 
switch ($this->mode) {
case 'event':
$this->_handlerObj->handleElement($el['name'], $el['attribs'], $data);
break;
case 'func':
$func = 'handleElement_' . $elem;
if (strchr($func, '.')) {
$func = str_replace('.', '_', $func);
}
if (method_exists($this->_handlerObj, $func)) {
call_user_func(array(&$this->_handlerObj, $func), $el['name'], $el['attribs'], $data);
}
break;
}
}
 
/**
* handle character data
*
* @access private
* @final
* @param resource xml parser resource
* @param string data
*/
function cdataHandler($xp, $data)
{
$this->_data[$this->_depth] .= $data;
}
 
/**
* handle a tag
*
* Implement this in your parser
*
* @access public
* @abstract
* @param string element name
* @param array attributes
* @param string character data
*/
function handleElement($name, $attribs, $data)
{
}
 
/**
* get the current tag depth
*
* The root tag is in depth 0.
*
* @access public
* @return integer
*/
function getCurrentDepth()
{
return $this->_depth;
}
 
/**
* add some string to the current ddata.
*
* This is commonly needed, when a document is parsed recursively.
*
* @access public
* @param string data to add
* @return void
*/
function addToData( $data )
{
$this->_data[$this->_depth] .= $data;
}
}
?>
/trunk/api/pear/XML/RSS.php
New file
0,0 → 1,359
<?php
// vim: set expandtab tabstop=4 shiftwidth=4 fdm=marker:
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Martin Jansen <mj@php.net> |
// | |
// +----------------------------------------------------------------------+
//
// $Id: RSS.php,v 1.1 2005-04-18 16:13:31 jpm Exp $
//
 
require_once 'XML/Parser.php';
 
/**
* RSS parser class.
*
* This class is a parser for Resource Description Framework (RDF) Site
* Summary (RSS) documents. For more information on RSS see the
* website of the RSS working group (http://www.purl.org/rss/).
*
* @author Martin Jansen <mj@php.net>
* @version $Revision: 1.1 $
* @access public
*/
class XML_RSS extends XML_Parser
{
// {{{ properties
 
/**
* @var string
*/
var $insideTag = '';
 
/**
* @var string
*/
var $activeTag = '';
 
/**
* @var array
*/
var $channel = array();
 
/**
* @var array
*/
var $items = array();
 
/**
* @var array
*/
var $item = array();
 
/**
* @var array
*/
var $image = array();
 
/**
* @var array
*/
var $textinput = array();
/**
* @var array
*/
var $textinputs = array();
 
/**
* @var array
*/
var $parentTags = array('CHANNEL', 'ITEM', 'IMAGE', 'TEXTINPUT');
 
/**
* @var array
*/
var $channelTags = array('TITLE', 'LINK', 'DESCRIPTION', 'IMAGE',
'ITEMS', 'TEXTINPUT');
 
/**
* @var array
*/
var $itemTags = array('TITLE', 'LINK', 'DESCRIPTION', 'PUBDATE');
 
/**
* @var array
*/
var $imageTags = array('TITLE', 'URL', 'LINK');
 
var $textinputTags = array('TITLE', 'DESCRIPTION', 'NAME', 'LINK');
 
/**
* List of allowed module tags
*
* Currently Dublin Core Metadata and the blogChannel RSS module
* are supported.
*
* @var array
*/
var $moduleTags = array('DC:TITLE', 'DC:CREATOR', 'DC:SUBJECT', 'DC:DESCRIPTION',
'DC:PUBLISHER', 'DC:CONTRIBUTOR', 'DC:DATE', 'DC:TYPE',
'DC:FORMAT', 'DC:IDENTIFIER', 'DC:SOURCE', 'DC:LANGUAGE',
'DC:RELATION', 'DC:COVERAGE', 'DC:RIGHTS',
'BLOGCHANNEL:BLOGROLL', 'BLOGCHANNEL:MYSUBSCRIPTIONS',
'BLOGCHANNEL:MYSUBSCRIPTIONS', 'BLOGCHANNEL:CHANGES');
 
// }}}
// {{{ Constructor
 
/**
* Constructor
*
* @access public
* @param mixed File pointer or name of the RDF file.
* @return void
*/
function XML_RSS($handle = '')
{
$this->XML_Parser();
 
if (@is_resource($handle)) {
$this->setInput($handle);
} elseif ($handle != '') {
$this->setInputFile($handle);
} else {
$this->raiseError('No filename passed.');
}
}
 
// }}}
// {{{ startHandler()
 
/**
* Start element handler for XML parser
*
* @access private
* @param object XML parser object
* @param string XML element
* @param array Attributes of XML tag
* @return void
*/
function startHandler($parser, $element, $attribs)
{
switch ($element) {
case 'CHANNEL':
case 'ITEM':
case 'IMAGE':
case 'TEXTINPUT':
$this->insideTag = $element;
break;
 
default:
$this->activeTag = $element;
}
}
 
// }}}
// {{{ endHandler()
 
/**
* End element handler for XML parser
*
* If the end of <item>, <channel>, <image> or <textinput>
* is reached, this function updates the structure array
* $this->struct[] and adds the field "type" to this array,
* that defines the type of the current field.
*
* @access private
* @param object XML parser object
* @param string
* @return void
*/
function endHandler($parser, $element)
{
if ($element == $this->insideTag) {
$this->insideTag = '';
$this->struct[] = array_merge(array('type' => strtolower($element)),
$this->last);
}
 
if ($element == 'ITEM') {
$this->items[] = $this->item;
$this->item = '';
}
 
if ($element == 'IMAGE') {
$this->images[] = $this->image;
$this->image = '';
}
 
if ($element == 'TEXTINPUT') {
$this->textinputs = $this->textinput;
$this->textinput = '';
}
 
$this->activeTag = '';
}
 
// }}}
// {{{ cdataHandler()
 
/**
* Handler for character data
*
* @access private
* @param object XML parser object
* @param string CDATA
* @return void
*/
function cdataHandler($parser, $cdata)
{
if (in_array($this->insideTag, $this->parentTags)) {
$tagName = strtolower($this->insideTag);
$var = $this->{$tagName . 'Tags'};
 
if (in_array($this->activeTag, $var) ||
in_array($this->activeTag, $this->moduleTags)) {
$this->_add($tagName, strtolower($this->activeTag),
$cdata);
}
}
}
 
// }}}
// {{{ defaultHandler()
 
/**
* Default handler for XML parser
*
* @access private
* @param object XML parser object
* @param string CDATA
* @return void
*/
function defaultHandler($parser, $cdata)
{
return;
}
 
// }}}
// {{{ _add()
 
/**
* Add element to internal result sets
*
* @access private
* @param string Name of the result set
* @param string Fieldname
* @param string Value
* @return void
* @see cdataHandler
*/
function _add($type, $field, $value)
{
if (empty($this->{$type}) || empty($this->{$type}[$field])) {
$this->{$type}[$field] = $value;
} else {
$this->{$type}[$field] .= $value;
}
 
$this->last = $this->{$type};
}
 
// }}}
// {{{ getStructure()
 
/**
* Get complete structure of RSS file
*
* @access public
* @return array
*/
function getStructure()
{
return (array)$this->struct;
}
 
// }}}
// {{{ getchannelInfo()
 
/**
* Get general information about current channel
*
* This function returns an array containing the information
* that has been extracted from the <channel>-tag while parsing
* the RSS file.
*
* @access public
* @return array
*/
function getChannelInfo()
{
return (array)$this->channel;
}
 
// }}}
// {{{ getItems()
 
/**
* Get items from RSS file
*
* This function returns an array containing the set of items
* that are provided by the RSS file.
*
* @access public
* @return array
*/
function getItems()
{
return (array)$this->items;
}
 
// }}}
// {{{ getImages()
 
/**
* Get images from RSS file
*
* This function returns an array containing the set of images
* that are provided by the RSS file.
*
* @access public
* @return array
*/
function getImages()
{
return (array)$this->images;
}
 
// }}}
// {{{ getTextinputs()
 
/**
* Get text input fields from RSS file
*
* @access public
* @return array
*/
function getTextinputs()
{
return (array)$this->textinputs;
}
 
// }}}
 
}
?>