Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
xml_array.inc
1 <?php
18 // From PEAR
19 //require_once 'XML/Parser.php';
20 
43 class XML_Array// extends XML_Parser
44 {
45 
61  var $_array_paths = Array();
62 
68  var $_results = Array();
69 
75  var $_path = Array();
76 
82  var $_path_ptrs = Array();
83 
89  var $_cdata = '';
90 
96  function XML_Array($arr_paths=Array())
97  {
98  $this->setArrayPaths($arr_paths);
99  }//end constructor
100 
101 
102  /*
103  * Sets the array paths
104  *
105  * @access public
106  */
107  function setArrayPaths($arr_paths)
108  {
109  $this->_array_paths = $arr_paths;
110 
111  }//end setArrayPaths()
112 
113  /*
114  * Maps a xml file to a objects tree
115  *
116  * @return mixed The objects tree (XML_tree or an Pear error)
117  * @access public
118  */
119  function &getArrayFromFile($filename, $arr_paths=Array())
120  {
121  if (count($arr_paths)) $this->setArrayPaths($arr_paths);
122 
123  $this->_initParse();
124 
125  $err = $this->setInputFile($filename);
126  if (PEAR::isError($err)) {
127  return $err;
128  }
129 
130  $err = $this->parse();
131  if (PEAR::isError($err)) {
132  return $err;
133  }
134 
135  return $this->_results;
136 
137  }//end getArrayFromFile()
138 
139  function getArrayFromString($str, $arr_paths=Array())
140  {
141  if (count($arr_paths)) $this->setArrayPaths($arr_paths);
142 
143  $this->_initParse();
144 
145  $err = $this->parseString($str);
146  if (PEAR::isError($err)) {
147  return $err;
148  }
149  return $this->_results;
150 
151  }//end getArrayFromString()
152 
153  /*
154  * Do some initialisation before any parsing
155  *
156  * @access private
157  */
158  function _initParse()
159  {
160  $this->close();
161 
162  $this->folding = false;
163  $this->XML_Parser(null, 'event');
164 
165  $this->_results = '';
166  $this->_cdata = '';
167  $this->_path = Array();
168  $this->_path_ptrs = Array();
169  $this->_path_types = Array();
170 
171  }//end _initParse()
172 
182  function startHandler($xp, $elem, &$attribs)
183  {
184 
185  // root element ?
186  if (!count($this->_path)) {
187  $this->_path[] = $elem;
188  $this->_path_ptrs[] = &$this->_results;
189  $this->_path_types[] = 's';
190 
191  // normal element
192  } else {
193 
194  // get a ref to the parent element
195  $parent = &$this->_path_ptrs[count($this->_path_ptrs) - 1];
196 
197  // we aren't going to deal with mixed contents for the moment
198  //if (!empty($this->cdata)) {
199  // $parent_id = 'obj' . ($this->i - 1);
200  // $parent =& $this->$parent_id;
201  // $parent->children[] = new $this->_node_class(null, $this->cdata);
202  //}
203 
204  // create this elements entry, need to check
205  // if it exists here so that we don't overright multiple entry
206  // elements contents
207  if (!isset($parent[$elem]) || !is_array($parent[$elem])) {
208  $parent[$elem] = Array();
209  }
210 
211  // OK, now because we have a parent, then that parent is a compound element, comprenday ?
212  $this->_path_types[count($this->_path_types) - 1] = 'c';
213 
214  $this->_path[] = $elem;
215  $this->_path_types[] = 's'; // every element start's out simple :)
216  $this->_path_ptrs[] = &$parent[$elem];
217 
218  // OK, this element in one of possibly many with the same name
219  // so what we have to do is create an indexed array with each element under it
220  $path_str = implode('/', $this->_path);
221  if (in_array($path_str, $this->_array_paths)) {
222  $i = count($parent[$elem]);
223  $parent[$elem][$i] = Array();
224 
225  $this->_path_ptrs[] = &$parent[$elem][$i];
226 
227  }
228 
229  }
230 
231  // Now add the attributes to the element, which is the one
232  // on the top of the ptrs stack
233  $i = count($this->_path_ptrs) - 1;
234  for (reset($attribs); null !== ($k = key($attribs)); next($attribs)) {
235  $this->_path_ptrs[$i]['@'.$k] = $attribs[$k];
236  }
237 
238  $this->_cdata = '';
239 
240  return null;
241 
242  }//end startHandler()
243 
252  function endHandler($xp, $elem)
253  {
254 
255  // if we aren't the root element, then add any data necessary
256  if (count($this->_path) > 1) {
257 
258 
259  // if this element is a simple element (is just data), add the value
260  if ($this->_path_types[count($this->_path_types) - 1] == 's' && $this->_cdata != '') {
261  $this->_path_ptrs[count($this->_path_ptrs) - 1]['value'] = $this->_cdata;
262  }
263 
264  // mixed contents
265  //if (count($node->children) > 0) {
266  // if (trim($this->cdata)) {
267  // $node->children[] = new $this->_node_class(null, $this->cdata);
268  // }
269  //} else {
270  // $node->set_content($this->cdata);
271  //}
272 
273  }//end if
274 
275  // OK, this element in one of possibly many with the same name
276  // so what we need to pop 2 elements of the ptr's array
277  // because we put 2 on in startHandler
278  $path_str = implode('/', $this->_path);
279  if (in_array($path_str, $this->_array_paths)) {
280  array_pop($this->_path_ptrs);
281  }
282  array_pop($this->_path_ptrs);
283  array_pop($this->_path_types);
284  array_pop($this->_path);
285 
286 
287  $this->_cdata = '';
288  return null;
289 
290  }//end endHandler()
291 
292  /*
293  * The xml character data handler
294  *
295  * @param mixed $xp ignored
296  * @param string $data PCDATA between tags
297  *
298  * @access private
299  */
300  function cdataHandler($xp, $data)
301  {
302  if (trim($data) != '') {
303  $this->_cdata .= $data;
304  }
305 
306  }//end cdataHandler()
307 
308  /*
309  * Close the parser and do any cleanup that is necessary
310  *
311  * This function now checks whether the parser is set before freeing it, because version 1.1.0+
312  * of XML_Parser frees itself when calling parse, making this throw undefined property errors
313  *
314  * @access public
315  */
316  function close()
317  {
318  if (!empty($this->parser) && is_resource($this->parser)) xml_parser_free($this->parser);
319 
320  }//end close()
321 
322 
323 }//end class
324 
325 ?>