XML parser now should (in theory) be working.
[isso.git] / xml.php
1 <?php
2 /*=====================================================================*\
3 || ################################################################### ||
4 || # Iris Studios Shared Object Framework [#]version[#]
5 || # --------------------------------------------------------------- # ||
6 || # All parts of this file are ©2003-[#]year[#] Iris Studios, Inc. No # ||
7 || # part of this file may be reproduced in any way: part or whole. # ||
8 || # --------------------------------------------------------------- # ||
9 || # ©2003 - [#]year[#] Iris Studios, Inc. | http://www.iris-studios.com # ||
10 || ################################################################### ||
11 \*=====================================================================*/
12
13 $OBJECT = 'XML Parser';
14 $CLASS = 'XML_Parser';
15 $OBJ = 'xml';
16
17 /**
18 * XML Parser
19 *
20 * This framework is a wrapper for a robust XML parser.
21 *
22 * @author Iris Studios, Inc.
23 * @copyright Copyright ©2003 - [#]year[#], Iris Studios, Inc.
24 * @version $Revision$
25 *
26 */
27 class XML_Parser
28 {
29 /**
30 * Global environment variables
31 *
32 * @var parser Current XML parser
33 * @var taginfo Array of all the processed tag data
34 * @var taghandler What to do for each tag encountered
35 * @var trimdata Trim CDATA elements?
36 * @var attrdata Data parsed from global attributes
37 * @var tagid Current tag ID in the document
38 * @var tagname Current tag name in the document
39 * @var tree Tag stack to use for proper nesting
40 * @var parent The tag's parent
41 */
42 var $parser = null;
43 var $taginfo = array();
44 var $taghandler = array();
45 var $trimdata = true;
46 var $attrdata = array();
47 var $tagid = -1;
48 var $tagname = '';
49 var $tree = array();
50 var $parent = -1;
51
52 /**
53 * Parse an XML file
54 *
55 * @param str XML file data
56 *
57 * @return array Array with all the XML data parsed
58 */
59 function parse($data)
60 {
61 global $_isso;
62
63 // reset all the parser data before starting
64 $this->taginfo = array();
65 $this->attrdata = array();
66 $this->tagid = -1;
67 $this->tagname = '';
68 $this->tree = array();
69 $this->parentid = -1;
70
71 // create a new parser
72 $this->parser = xml_parser_create();
73 xml_set_object($this->parser, $this);
74 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
75 xml_set_element_handler($this->parser, '_tag_start', '_tag_end');
76 xml_set_character_data_handler($this->parser, '_cdata');
77
78 // parse the data and check for errors
79 if (!xml_parse($this->parser, $data))
80 {
81 $error['code'] = xml_get_error_code($this->parser);
82 $error['string'] = xml_error_string($error['code']);
83 $error['line'] = xml_get_current_line_number($this->parser);
84 $error['column'] = xml_get_current_column_number($this->parser);
85 print(sprintf("XML Error: %s (%d) at line %d colunn %d", $error['string'], $error['code'], $error['line'], $error['column']));
86 exit;
87 }
88
89 // destroy the parser
90 xml_parser_free($this->parser);
91
92 // data manipulation -- kind of resource intensive :-/
93 foreach ($this->taginfo AS $tagname => $parents)
94 {
95 foreach ($parents AS $parentid => $ids)
96 {
97 foreach ($ids AS $tagid => $data)
98 {
99 // trim data if necessary
100 if ($this->trimdata)
101 {
102 $_isso->debug("data trim: on");
103 if (($trimmed = trim($data)) != '')
104 {
105 $data = $trimmed;
106 }
107 }
108
109 // if we have a data handler, operate it now
110 if (isset($this->taghandler["$tagname"]))
111 {
112 $_isso->debug("handler: " . $this->taghandler["$tagname"]);
113 if (function_exists($this->taghandler["$tagname"]))
114 {
115 $data = $this->taghandler["$tagname"]($data, $this);
116 }
117 else
118 {
119 trigger_error('Could not find the function [' . $this->taghandler["$tagname"] . '()] for the XML tag "' . $tagname . '"', ERR_FATAL);
120 }
121 }
122
123 $return["$tagid"] = array('tagid' => $tagid, 'tagname' => $tagname, 'parentid' => $parentid, 'attributes' => $this->attrdata["$tagid"], 'data' => $data);
124 }
125 }
126 }
127
128 // done... send the results back
129 return $return;
130 }
131
132 /**
133 * Process the opening location of an XML tag
134 *
135 * @param res XML parser
136 * @param str Tag name
137 * @param array Tag attributes
138 */
139 function _tag_start($parser, $name, $attributes)
140 {
141 // we're opening a new tag
142 $this->tagid++;
143 $this->tagname = $name;
144
145 // copy all tag attributes
146 array_walk($attributes, 'trim');
147 $this->attrdata[ $this->tagid ] = $attributes;
148
149 $this->parent = current($this->tree);
150 if ($this->parent === false)
151 {
152 $this->parent = -1;
153 }
154 // advance the parent counter because the tree is yet to be updated
155 else
156 {
157 $this->parent++;
158 }
159
160 // initialize the data set
161 $this->taginfo["$name"][ $this->parent ][ $this->tagid ] = '';
162
163 // add the current tag into the tree
164 $this->tree[] = $this->tagid;
165 }
166
167 /**
168 * Process XML CDATA
169 *
170 * @param res XML parser
171 * @param str CDATA from tag
172 */
173 function _cdata($parser, $data)
174 {
175 // read in the CDATA
176 if ($this->parent == $this->tagid)
177 {
178 if (!isset($this->taginfo[ $this->tagname ][ $this->parent ][ $this->tagid ]))
179 {
180 $this->taginfo[ $this->tagname ][ $this->parent ][ $this->tagid ] = '';
181 }
182
183 $this->taginfo[ $this->tagname ][ $this->parent ][ $this->tagid ] .= $data;
184 }
185 else
186 {
187 $this->taginfo[ $this->tagname ][ $this->parent ][ $this->tagid ] .= $data;
188 }
189 }
190
191 /**
192 * Process the closing of an XML tag
193 *
194 * @param res XML parser
195 * @param str Tag name
196 */
197 function _tag_end($parser, $name)
198 {
199 // make sure that we're always at the end of the tree
200 end($this->tree);
201 }
202 }
203
204 /*=====================================================================*\
205 || ###################################################################
206 || # $HeadURL$
207 || # $Id$
208 || ###################################################################
209 \*=====================================================================*/
210 ?>