// description of your code here
1
2 大家都知é?“PHP4䏿²¡æœ‰SimpleXML扩展,è¦?XMLè§£æž?æˆ?数组是件麻烦的事,最近æ£å¥½ç”¨åˆ°ç›¸å…³æŠ€æœ¯ï¼ŒäºŽæ˜¯å°±è‡ªå·±å†™ä¸€ä¸ªï¼Œä»¥ä¸‹æ˜¯æº?代ç ?:
3
4 SofeeXmlParser.php
5 <?php
6 /*
7 +----------------------------------------------------------------------+
8 | SofeeFramework for PHP 4 |
9 +----------------------------------------------------------------------+
10 | Copyright (c) 2004-2005 Sofee Development Team.(http://www.sofee.cn) |
11 +----------------------------------------------------------------------+
12 | This source file is subject to version 1.00 of the Sofee license, |
13 | that is bundled with this package in the file LICENSE, and is |
14 | available through the world-wide-web at the following url: |
15 | http://www.sofee.cn/license/1_00.txt. |
16 | If you did not receive a copy of the Sofee license and are unable to |
17 | obtain it through the world-wide-web, please send a note to |
18 | license@sofee.cn so we can mail you a copy immediately. |
19 +----------------------------------------------------------------------+
20 | Author: Justin Wu <ezdevelop@gmail.com> |
21 +----------------------------------------------------------------------+
22 */
23
24 /* $Id: SofeeXmlParser.php,v 1.3 2005/05/30 06:30:14 wenlong Exp $ */
25
26 /**
27 * Sofee XML Parser class - This is an XML parser based on PHP's "xml" extension.
28 *
29 * The SofeeXmlParser class provides a very simple and easily usable toolset to convert XML
30 * to an array that can be processed with array iterators.
31 *
32 * @package SofeeFramework
33 * @access public
34 * @version $Revision: 1.1 $
35 * @author Justin Wu <wenlong@php.net>
36 * @homepage http://www.sofee.cn
37 * @copyright Copyright (c) 2004-2005 Sofee Development Team.(http://www.sofee.cn)
38 * @since 2005-05-30
39 * @see PEAR:XML_Parser | SimpleXML extension
40 */
41 class SofeeXmlParser {
42
43 /**
44 * XML parser handle
45 *
46 * @var resource
47 * @see xml_parser_create()
48 */
49 var $parser;
50
51 /**
52 * source encoding
53 *
54 * @var string
55 */
56 var $srcenc;
57
58 /**
59 * target encoding
60 *
61 * @var string
62 */
63 var $dstenc;
64
65 /**
66 * the original struct
67 *
68 * @access private
69 * @var array
70 */
71 var $_struct = array();
72
73 /**
74 * Constructor
75 *
76 * @access public
77 * @param mixed [$srcenc] source encoding
78 * @param mixed [$dstenc] target encoding
79 * @return void
80 * @since
81 */
82 function SofeeXmlParser($srcenc = null, $dstenc = null) {
83 $this->srcenc = $srcenc;
84 $this->dstenc = $dstenc;
85
86 // initialize the variable.
87 $this->parser = null;
88 $this->_struct = array();
89 }
90
91 /**
92 * Free the resources
93 *
94 * @access public
95 * @return void
96 **/
97 function free() {
98 if (isset($this->parser) && is_resource($this->parser)) {
99 xml_parser_free($this->parser);
100 unset($this->parser);
101 }
102 }
103
104 /**
105 * Parses the XML file
106 *
107 * @access public
108 * @param string [$file] the XML file name
109 * @return void
110 * @since
111 */
112 function parseFile($file) {
113 $data = @file_get_contents($file) or die("Can't open file $file for reading!");
114 $this->parseString($data);
115 }
116
117 /**
118 * Parses a string.
119 *
120 * @access public
121 * @param string [$data] XML data
122 * @return void
123 */
124 function parseString($data) {
125 if ($this->srcenc === null) {
126 $this->parser = @xml_parser_create() or die('Unable to create XML parser resource.');
127 } else {
128 $this->parser = @xml_parser_create($this->srcenc) or die('Unable to create XML parser resource with '. $this->srcenc .' encoding.');
129 }
130
131 if ($this->dstenc !== null) {
132 @xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->dstenc) or die('Invalid target encoding');
133 }
134 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); // lowercase tags
135 xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1); // skip empty tags
136 if (!xml_parse_into_struct($this->parser, $data, &$this->_struct)) {
137 printf("XML error: %s at line %d",
138 xml_error_string(xml_get_error_code($this->parser)),
139 xml_get_current_line_number($this->parser)
140 );
141 $this->free();
142 exit();
143 }
144
145 $this->_count = count($this->_struct);
146 $this->free();
147 }
148
149 /**
150 * return the data struction
151 *
152 * @access public
153 * @return array
154 */
155 function getTree() {
156 $i = 0;
157 $tree = array();
158
159 $tree = $this->addNode(
160 $tree,
161 $this->_struct[$i]['tag'],
162 (isset($this->_struct[$i]['value'])) ? $this->_struct[$i]['value'] : '',
163 (isset($this->_struct[$i]['attributes'])) ? $this->_struct[$i]['attributes'] : '',
164 $this->getChild($i)
165 );
166
167 unset($this->_struct);
168 return ($tree);
169 }
170
171 /**
172 * recursion the children node data
173 *
174 * @access public
175 * @param integer [$i] the last struct index
176 * @return array
177 */
178 function getChild(&$i) {
179 // contain node data
180 $children = array();
181
182 // loop
183 while (++$i < $this->_count) {
184 // node tag name
185 $tagname = $this->_struct[$i]['tag'];
186 $value = isset($this->_struct[$i]['value']) ? $this->_struct[$i]['value'] : '';
187 $attributes = isset($this->_struct[$i]['attributes']) ? $this->_struct[$i]['attributes'] : '';
188
189 switch ($this->_struct[$i]['type']) {
190 case 'open':
191 // node has more children
192 $child = $this->getChild($i);
193 // append the children data to the current node
194 $children = $this->addNode($children, $tagname, $value, $attributes, $child);
195 break;
196 case 'complete':
197 // at end of current branch
198 $children = $this->addNode($children, $tagname, $value, $attributes);
199 break;
200 case 'cdata':
201 // node has CDATA after one of it's children
202 $children['value'] .= $value;
203 break;
204 case 'close':
205 // end of node, return collected data
206 return $children;
207 break;
208 }
209
210 }
211 //return $children;
212 }
213
214 /**
215 * Appends some values to an array
216 *
217 * @access public
218 * @param array [$target]
219 * @param string [$key]
220 * @param string [$value]
221 * @param array [$attributes]
222 * @param array [$inner] the children
223 * @return void
224 * @since
225 */
226 function addNode($target, $key, $value = '', $attributes = '', $child = '') {
227 if (!isset($target[$key]['value']) && !isset($target[$key][0])) {
228 if ($child != '') {
229 $target[$key] = $child;
230 }
231 if ($attributes != '') {
232 foreach ($attributes as $k => $v) {
233 $target[$key][$k] = $v;
234 }
235 }
236
237 $target[$key]['value'] = $value;
238 } else {
239 if (!isset($target[$key][0])) {
240 // is string or other
241 $oldvalue = $target[$key];
242 $target[$key] = array();
243 $target[$key][0] = $oldvalue;
244 $index = 1;
245 } else {
246 // is array
247 $index = count($target[$key]);
248 }
249
250 if ($child != '') {
251 $target[$key][$index] = $child;
252 }
253
254 if ($attributes != '') {
255 foreach ($attributes as $k => $v) {
256 $target[$key][$index][$k] = $v;
257 }
258 }
259 $target[$key][$index]['value'] = $value;
260 }
261 return $target;
262 }
263
264 }
265
266 调用方�:
267 <?php
268 $file = 'test.xml';
269 require_once('SofeeXmlParser.php');
270 $xml = new SofeeXmlParser();
271 $xml->parseFile($file);
272 $tree = $xml->getTree();
273 unset($xml);
274 print "<pre>";
275 print_r($tree);
276 print "</pre>";
277 ?>
278
279 test.xml文件内容:
280 <?xml version="1.0" encoding="GBK"?>
281 <nba update="2005-06-07">
282 <team id="46">皇家马德里</team>
283 <team id="47">尤文图斯</team>
284 <team id="51">ç?«ç®</team>
285 <team id="52">æ²ƒå°”å¤«æ–¯å ¡</team>
286 <team id="53">巴塞罗那</team>
287 <team id="54">太阳</team>
288 </nba>
289
290 输出结果:
291
292
293 Array
294 (
295 [nba] => Array
296 (
297 [team] => Array
298 (
299 [0] => Array
300 (
301 [id] => 46
302 [value] => 皇家马德里
303 )
304
305 [1] => Array
306 (
307 [id] => 47
308 [value] => 尤文图斯
309 )
310
311 [2] => Array
312 (
313 [id] => 51
314 [value] => ç?«ç®
315 )
316
317 [3] => Array
318 (
319 [id] => 52
320 [value] => æ²ƒå°”å¤«æ–¯å ¡
321 )
322
323 [4] => Array
324 (
325 [id] => 53
326 [value] => 巴塞罗那
327 )
328
329 [5] => Array
330 (
331 [id] => 54
332 [value] => 太阳
333 )
334
335 )
336
337 [update] => 2005-06-07
338 [value] =>
339 )
340
341 )
342
343
344 Array
345 (
346 [nba] => Array
347 (
348 [team] => Array
349 (
350 [0] => Array
351 (
352 [id] => 46
353 [value] => 皇家马德里
354 )
355
356 [1] => Array
357 (
358 [id] => 47
359 [value] => 尤文图斯
360 )
361
362 [2] => Array
363 (
364 [id] => 51
365 [value] => ç?«ç®
366 )
367
368 [3] => Array
369 (
370 [id] => 52
371 [value] => æ²ƒå°”å¤«æ–¯å ¡
372 )
373
374 [4] => Array
375 (
376 [id] => 53
377 [value] => 巴塞罗那
378 )
379
380 [5] => Array
381 (
382 [id] => 54
383 [value] => 太阳
384 )
385
386 )
387
388 [update] => 2005-06-07
389 [value] =>
390 )
391
392 )
393
394