Updated PEAR and PEAR packages.
[timetracker.git] / WEB-INF / lib / pear / PEAR / XMLParser.php
1 <?php
2 /**
3  * PEAR_XMLParser
4  *
5  * PHP versions 4 and 5
6  *
7  * @category   pear
8  * @package    PEAR
9  * @author     Greg Beaver <cellog@php.net>
10  * @author     Stephan Schmidt (original XML_Unserializer code)
11  * @copyright  1997-2009 The Authors
12  * @license   http://opensource.org/licenses/bsd-license New BSD License
13  * @link       http://pear.php.net/package/PEAR
14  * @since      File available since Release 1.4.0a1
15  */
16
17 /**
18  * Parser for any xml file
19  * @category  pear
20  * @package   PEAR
21  * @author    Greg Beaver <cellog@php.net>
22  * @author    Stephan Schmidt (original XML_Unserializer code)
23  * @copyright 1997-2009 The Authors
24  * @license   http://opensource.org/licenses/bsd-license New BSD License
25  * @version   Release: 1.10.1
26  * @link      http://pear.php.net/package/PEAR
27  * @since     Class available since Release 1.4.0a1
28  */
29 class PEAR_XMLParser
30 {
31     /**
32      * unserilialized data
33      * @var string $_serializedData
34      */
35     var $_unserializedData = null;
36
37     /**
38      * name of the root tag
39      * @var string $_root
40      */
41     var $_root = null;
42
43     /**
44      * stack for all data that is found
45      * @var array    $_dataStack
46      */
47     var $_dataStack = array();
48
49     /**
50      * stack for all values that are generated
51      * @var array    $_valStack
52      */
53     var $_valStack = array();
54
55     /**
56      * current tag depth
57      * @var int    $_depth
58      */
59     var $_depth = 0;
60
61     /**
62      * The XML encoding to use
63      * @var string $encoding
64      */
65     var $encoding = 'ISO-8859-1';
66
67     /**
68      * @return array
69      */
70     function getData()
71     {
72         return $this->_unserializedData;
73     }
74
75     /**
76      * @param string xml content
77      * @return true|PEAR_Error
78      */
79     function parse($data)
80     {
81         if (!extension_loaded('xml')) {
82             include_once 'PEAR.php';
83             return PEAR::raiseError("XML Extension not found", 1);
84         }
85         $this->_dataStack =  $this->_valStack = array();
86         $this->_depth = 0;
87
88         if (
89             strpos($data, 'encoding="UTF-8"')
90             || strpos($data, 'encoding="utf-8"')
91             || strpos($data, "encoding='UTF-8'")
92             || strpos($data, "encoding='utf-8'")
93         ) {
94             $this->encoding = 'UTF-8';
95         }
96
97         $xp = xml_parser_create($this->encoding);
98         xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0);
99         xml_set_object($xp, $this);
100         xml_set_element_handler($xp, 'startHandler', 'endHandler');
101         xml_set_character_data_handler($xp, 'cdataHandler');
102         if (!xml_parse($xp, $data)) {
103             $msg = xml_error_string(xml_get_error_code($xp));
104             $line = xml_get_current_line_number($xp);
105             xml_parser_free($xp);
106             include_once 'PEAR.php';
107             return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2);
108         }
109         xml_parser_free($xp);
110         return true;
111     }
112
113     /**
114      * Start element handler for XML parser
115      *
116      * @access private
117      * @param  object $parser  XML parser object
118      * @param  string $element XML element
119      * @param  array  $attribs attributes of XML tag
120      * @return void
121      */
122     function startHandler($parser, $element, $attribs)
123     {
124         $this->_depth++;
125         $this->_dataStack[$this->_depth] = null;
126
127         $val = array(
128             'name'         => $element,
129             'value'        => null,
130             'type'         => 'string',
131             'childrenKeys' => array(),
132             'aggregKeys'   => array()
133        );
134
135         if (count($attribs) > 0) {
136             $val['children'] = array();
137             $val['type'] = 'array';
138             $val['children']['attribs'] = $attribs;
139         }
140
141         array_push($this->_valStack, $val);
142     }
143
144     /**
145      * post-process data
146      *
147      * @param string $data
148      * @param string $element element name
149      */
150     function postProcess($data, $element)
151     {
152         return trim($data);
153     }
154
155     /**
156      * End element handler for XML parser
157      *
158      * @access private
159      * @param  object XML parser object
160      * @param  string
161      * @return void
162      */
163     function endHandler($parser, $element)
164     {
165         $value = array_pop($this->_valStack);
166         $data  = $this->postProcess($this->_dataStack[$this->_depth], $element);
167
168         // adjust type of the value
169         switch (strtolower($value['type'])) {
170             // unserialize an array
171             case 'array':
172                 if ($data !== '') {
173                     $value['children']['_content'] = $data;
174                 }
175
176                 $value['value'] = isset($value['children']) ? $value['children'] : array();
177                 break;
178
179             /*
180              * unserialize a null value
181              */
182             case 'null':
183                 $data = null;
184                 break;
185
186             /*
187              * unserialize any scalar value
188              */
189             default:
190                 settype($data, $value['type']);
191                 $value['value'] = $data;
192                 break;
193         }
194
195         $parent = array_pop($this->_valStack);
196         if ($parent === null) {
197             $this->_unserializedData = &$value['value'];
198             $this->_root = &$value['name'];
199             return true;
200         }
201
202         // parent has to be an array
203         if (!isset($parent['children']) || !is_array($parent['children'])) {
204             $parent['children'] = array();
205             if ($parent['type'] != 'array') {
206                 $parent['type'] = 'array';
207             }
208         }
209
210         if (!empty($value['name'])) {
211             // there already has been a tag with this name
212             if (in_array($value['name'], $parent['childrenKeys'])) {
213                 // no aggregate has been created for this tag
214                 if (!in_array($value['name'], $parent['aggregKeys'])) {
215                     if (isset($parent['children'][$value['name']])) {
216                         $parent['children'][$value['name']] = array($parent['children'][$value['name']]);
217                     } else {
218                         $parent['children'][$value['name']] = array();
219                     }
220                     array_push($parent['aggregKeys'], $value['name']);
221                 }
222                 array_push($parent['children'][$value['name']], $value['value']);
223             } else {
224                 $parent['children'][$value['name']] = &$value['value'];
225                 array_push($parent['childrenKeys'], $value['name']);
226             }
227         } else {
228             array_push($parent['children'],$value['value']);
229         }
230         array_push($this->_valStack, $parent);
231
232         $this->_depth--;
233     }
234
235     /**
236      * Handler for character data
237      *
238      * @access private
239      * @param  object XML parser object
240      * @param  string CDATA
241      * @return void
242      */
243     function cdataHandler($parser, $cdata)
244     {
245         $this->_dataStack[$this->_depth] .= $cdata;
246     }
247 }