File: /home/confeduphaar/backip-old-files/plugins/vmpayment/sofort/sofort/library/helper/xml_to_array.php
<?php
defined('_JEXEC') or die('Restricted access');
/**
* @author SOFORT AG (integration@sofort.com)
* @link http://www.sofort.com/
*
* Copyright (c) 2012 SOFORT AG
*
* Released under the GNU General Public License (Version 2)
* [http://www.gnu.org/licenses/gpl-2.0.html]
*/
require_once('xml_to_array_exception.php');
require_once('xml_to_array_node.php');
/**
*
* XML To Array conversion
*/
class XmlToArray {
/**
* Holds start tags in a row.
* Used for error reporting and counting the current depth
* @var array
*/
private $_tagStack = array();
/**
* Reference to the current node the parser is at
* @var XmlToArrayNode
*/
private $_CurrentXmlToArrayNode = null;
/**
* Object reference for logging purposes
* @var Object
*/
private $_Object = null;
/**
* stop parsing when maxDepth is exceeded, defaults to no maximum (=0).
*
* @var $_maxDepth int
*/
private $_maxDepth = 0;
private static $_htmlEntityExceptions = array(
'€' => '€',
);
/**
* Loads XML into array representation.
* @param string $input
* @param int $maxDepth
* @throws XmlToArrayException
*/
public function __construct($input, $maxDepth = 20) {
if (!is_string($input)) throw new XmlToArrayException('No valid input.');
$this->_maxDepth = $maxDepth;
$XMLParser = xml_parser_create();
xml_parser_set_option($XMLParser, XML_OPTION_SKIP_WHITE, false);
xml_parser_set_option($XMLParser, XML_OPTION_CASE_FOLDING, false);
xml_parser_set_option($XMLParser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
xml_set_character_data_handler($XMLParser, array($this, '_contents'));
xml_set_default_handler($XMLParser, array($this, '_default'));
xml_set_element_handler($XMLParser, array($this, '_start'), array($this, '_end'));
xml_set_external_entity_ref_handler($XMLParser, array($this, '_externalEntity'));
xml_set_notation_decl_handler($XMLParser, array($this, '_notationDecl'));
xml_set_processing_instruction_handler($XMLParser, array($this, '_processingInstruction'));
xml_set_unparsed_entity_decl_handler($XMLParser, array($this, '_unparsedEntityDecl'));
if (!xml_parse($XMLParser, $input, true)) {
$errorCode = xml_get_error_code($XMLParser);
$message = sprintf('%s. line: %d, char: %d'.($this->_tagStack ? ', tag: %s' : ''),
xml_error_string($errorCode),
xml_get_current_line_number($XMLParser),
xml_get_current_column_number($XMLParser)+1,
implode('->', $this->_tagStack));
xml_parser_free($XMLParser);
throw new XmlToArrayException($message, $errorCode);
}
xml_parser_free($XMLParser);
}
/**
*
* Log messages (debugging purpose)
* @param string $msg
* @param int $type
*/
public function log($msg, $type = 2) {
if (class_exists('Object')) {
!($this->_Object instanceof Object) && $this->_Object = new Object();
return $this->_Object->log($msg, $type);
}
return false;
}
/**
* Returns parsed XML as array structure
* @return array
*/
public function toArray($simpleStructure = false) {
return $this->_CurrentXmlToArrayNode->render($simpleStructure);
}
/**
* Static entry point
* @param string $input
* @param bool $simpleStructure
* @param int $maxDepth only parse XML to the provided depth
* @return array
* @throws XmlToArrayException
*/
public static function render($input, $simpleStructure = false, $maxDepth = 20) {
$Instance = new XmlToArray($input, $maxDepth);
return $Instance->toArray($simpleStructure);
}
/**
* Handles cdata of the XML (user data between the tags)
* @param resource $parser a resource handle of the XML parser
* @param string $data
*/
private function _contents($parser, $data) {
if (trim($data) !== '' && $this->_CurrentXmlToArrayNode instanceof XmlToArrayNode) $this->_CurrentXmlToArrayNode->setData($data);
}
/**
* Default handler for all other XML sections not implemented as callback
* @param resource $parser a resource handle of the XML parser
* @param mixed $data
* @throws XmlToArrayException
*/
private function _default($parser, $data) {
$data = trim($data);
if (in_array($data, get_html_translation_table(HTML_ENTITIES))) {
$this->_CurrentXmlToArrayNode instanceof XmlToArrayNode && $this->_CurrentXmlToArrayNode->setData(html_entity_decode($data));
} elseif ($data && isset(self::$_htmlEntityExceptions[$data])) {
$this->_CurrentXmlToArrayNode instanceof XmlToArrayNode && $this->_CurrentXmlToArrayNode->setData(self::$_htmlEntityExceptions[$data]);
} elseif ($data && is_string($data) && strpos($data, '<!--') === false && strpos($data, '<?xml') === false) {
if (getenv('sofortDebug') == 'true') {
trigger_error('Default data handler used. The data passed was: '.$data, E_USER_WARNING);
throw new XmlToArrayException('Unknown error occurred');
}
}
}
/**
* Handler for end tags
* @param resource $parser a resource handle of the XML parser
* @param string $name
*/
private function _end($parser, $name) {
array_pop($this->_tagStack);
if ($this->_CurrentXmlToArrayNode instanceof XmlToArrayNode) {
$this->_CurrentXmlToArrayNode->setClosed();
$breaker = 0;
// step up the stack and close all tags as long as current tag is reached in stack
if ($this->_CurrentXmlToArrayNode->getName() != $name) {
do {
$this->_CurrentXmlToArrayNode = $this->_CurrentXmlToArrayNode->getParentXmlToArrayNode();
$this->_CurrentXmlToArrayNode->setClosed();
if ($breaker > 100) {
trigger_error('Had to break out from endless loop.', E_USER_WARNING);
break;
}
++$breaker;
} while($this->_CurrentXmlToArrayNode->getName() != $name);
} elseif ($this->_CurrentXmlToArrayNode->hasParentXmlToArrayNode()) {
$this->_CurrentXmlToArrayNode = $this->_CurrentXmlToArrayNode->getParentXmlToArrayNode();
}
}
}
/**
*
* External Entity, no operation
* @param unknown_type $parser
* @param unknown_type $openEntityNames
* @param unknown_type $base
* @param unknown_type $systemId
* @param unknown_type $publicId
*/
private function _externalEntity($parser , $openEntityNames , $base , $systemId , $publicId) {
// noop
}
/**
*
* Notation Decl, no operation
* @param unknown_type $parser
* @param unknown_type $notationName
* @param unknown_type $base
* @param unknown_type $systemId
* @param unknown_type $publicId
*/
private function _notationDecl($parser , $notationName , $base , $systemId , $publicId) {
// noop
}
/**
*
* Processing Instruction, no operation
* @param unknown_type $parser
* @param unknown_type $target
* @param unknown_type $data
*/
private function _processingInstruction($parser, $target, $data) {
// noop
}
/**
*
* Unparsed Entity Decl, no operation
* @param unknown_type $parser
* @param unknown_type $entityName
* @param unknown_type $base
* @param unknown_type $systemId
* @param unknown_type $publicd
* @param unknown_type $notationName
*/
private function _unparsedEntityDecl($parser , $entityName , $base , $systemId , $publicd , $notationName) {
// noop
}
/**
* Handler for start tags
* @param resource $parser a resource handle of the XML parser
* @param string $name
* @param array $attributes
* @todo add check on max depth
*/
private function _start($parser, $name, $attributes) {
$this->_tagStack[] = $name;
if ($this->_maxDepth && count($this->_tagStack) > $this->_maxDepth) {
throw new XmlToArrayException('Parse Error: max depth exceeded.', '7005');
}
$XmlToArrayNode = new XmlToArrayNode($name, $attributes);
if ($this->_CurrentXmlToArrayNode instanceof XmlToArrayNode && $this->_CurrentXmlToArrayNode->isOpen()) {
$this->_CurrentXmlToArrayNode->addChild($XmlToArrayNode);
$XmlToArrayNode->setParentXmlToArrayNode($this->_CurrentXmlToArrayNode);
}
$this->_CurrentXmlToArrayNode = $XmlToArrayNode;
}
}
?>