Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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