Source of file xmlToArray.php
Size: 8,055 Bytes - Last Modified: 2021-12-24T05:16:28+00:00
/var/www/docs.ssmods.com/process/src/code/thirdparty/lib/xmlToArray.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 | <?php require_once('xmlToArrayException.php'); require_once('xmlToArrayNode.php'); /** * XML To Array conversion * * @author SOFORT AG (integration@sofort.com) * * @copyright 2010-2014 SOFORT AG * * @license Released under the GNU LESSER GENERAL PUBLIC LICENSE (Version 3) * @license http://www.gnu.org/licenses/lgpl.html * * @version SofortLib 2.1.1 * * @link http://www.sofort.com/ official website */ class XmlToArray { /** * Reference to the current node the parser is at * * @var $_CurrentXmlToArrayNode */ private $_CurrentXmlToArrayNode = null; /** * Array of entities which are not in the translation table used by htmlspecialchars and htmlentities * * @var array $_htmlEntityExceptions */ private static $_htmlEntityExceptions = array( '€' => '€', ); /** * stop parsing when maxDepth is exceeded, defaults to no maximum (=0). * * @var int $_maxDepth */ private $_maxDepth = 0; /** * Object reference for logging purposes * * @var Object $_Object */ private $_Object = null; /** * Holds start tags in a row. * Used for error reporting and counting the current depth * * @var array $_tagStack */ private $_tagStack = array(); /** * Loads XML into array representation. * * @param string $input * @param int $maxDepth (default 20) * @throws XmlToArrayException * @return \XmlToArray */ 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')); 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 (default 2) * @return array|bool */ 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; } /** * Static entry point * * @param string $input * @param bool $simpleStructure (default false) * @param int $maxDepth only parse XML to the provided depth (default 20) * @throws XmlToArrayException * @return array */ public static function render($input, $simpleStructure = false, $maxDepth = 20) { $Instance = new XmlToArray($input, $maxDepth); return $Instance->toArray($simpleStructure); } /** * Returns parsed XML as array structure * * @param bool $simpleStructure (default false) * @return array */ public function toArray($simpleStructure = false) { return $this->_CurrentXmlToArrayNode->render($simpleStructure); } /** * Handles cdata of the XML (user data between the tags) * * @param resource $parser a resource handle of the XML parser * @param string $data * @return void */ 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 * @return void */ private function _default($parser, $data) { $data = trim($data); if (in_array($data, get_html_translation_table(HTML_ENTITIES))) { if ($this->_CurrentXmlToArrayNode instanceof XmlToArrayNode) { $this->_CurrentXmlToArrayNode->setData(html_entity_decode($data)); } } elseif ($data && isset(self::$_htmlEntityExceptions[$data])) { if ($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 * @return void */ 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(); } } } /** * Handler for start tags * * @param resource $parser a resource handle of the XML parser * @param string $name * @param array $attributes * @throws XmlToArrayException * @return void */ 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; } } |