FusionDirectory
class_xml.inc
Go to the documentation of this file.
1 <?php
2 /*
3  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
4 
5  Copyright (C) 2003-2010 Cajus Pollmeier
6  Copyright (C) 2011-2020 FusionDirectory
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22 
32 class xml
33 {
43  static function xml2array ($contents, $get_attributes = 1, $priority = 'tag')
44  {
45  if (!$contents) {
46  return [];
47  }
48 
49  if (!function_exists('xml_parser_create')) {
50  trigger_error('xml_parser_create function does not exists');
51  return [];
52  }
53 
54  //Get the XML parser of PHP - PHP must have this module for the parser to work
55  $parser = xml_parser_create('');
56  xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); // http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss
57  xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
58  xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
59  xml_parse_into_struct($parser, trim($contents), $xml_values);
60  xml_parser_free($parser);
61 
62  if (!$xml_values) {
63  return;
64  }
65 
66  // Initializations
67  $xml_array = [];
68 
69  // Reference
70  $current = &$xml_array;
71 
72  // Go through the tags.
73  // Multiple tags with same name will be turned into an array
74  $repeated_tag_index = [];
75  foreach ($xml_values as $data) {
76  $result = [];
77  $attributes_data = [];
78 
79  if (isset($data['value'])) {
80  if ($priority == 'tag') {
81  $result = $data['value'];
82  } else {
83  // Put the value in a assoc array if we are in the 'Attribute' mode
84  $result['value'] = $data['value'];
85  }
86  }
87 
88  //Set the attributes too.
89  if (isset($data['attributes']) and $get_attributes) {
90  foreach ($data['attributes'] as $attr => $val) {
91  if ($priority == 'tag') {
92  $attributes_data[$attr] = $val;
93  } else {
94  // Set all the attributes in a array called 'attr'
95  $result['attr'][$attr] = $val;
96  }
97  }
98  }
99 
100  // See tag status and do the needed.
101  if ($data['type'] == 'open') {
102  // The starting of the tag '<tag>'
103  $parent[$data['level'] - 1] = &$current;
104  if (!is_array($current) or (!in_array($data['tag'], array_keys($current)))) {
105  // Insert New tag
106  $current[$data['tag']] = $result;
107  if ($attributes_data) {
108  $current[$data['tag']. '_attr'] = $attributes_data;
109  }
110  $repeated_tag_index[$data['tag'].'_'.$data['level']] = 1;
111 
112  $current = &$current[$data['tag']];
113  } else {
114  // There was another element with the same tag name
115 
116  if (isset($current[$data['tag']][0])) {
117  // If there is a 0th element it is already an array
118  $current[$data['tag']][$repeated_tag_index[$data['tag'].'_'.$data['level']]] = $result;
119  $repeated_tag_index[$data['tag'].'_'.$data['level']]++;
120  } else {
121  // This section will make the value an array if multiple tags with the same name appear together
122  // This will combine the existing item and the new item together to make an array
123  $current[$data['tag']] = [$current[$data['tag']],$result];
124  $repeated_tag_index[$data['tag'].'_'.$data['level']] = 2;
125 
126  if (isset($current[$data['tag'].'_attr'])) {
127  // The attribute of the last(0th) tag must be moved as well
128  $current[$data['tag']]['0_attr'] = $current[$data['tag'].'_attr'];
129  unset($current[$data['tag'].'_attr']);
130  }
131  }
132  $last_item_index = $repeated_tag_index[$data['tag'].'_'.$data['level']] - 1;
133  $current = &$current[$data['tag']][$last_item_index];
134  }
135  } elseif ($data['type'] == "complete") {
136  // Tags that ends in 1 line '<tag />'
137  // See if the key is already taken.
138  if (!isset($current[$data['tag']])) {
139  // New Key
140  $current[$data['tag']] = $result;
141  $repeated_tag_index[$data['tag'].'_'.$data['level']] = 1;
142  if ($priority == 'tag' and $attributes_data) {
143  $current[$data['tag']. '_attr'] = $attributes_data;
144  }
145  } else {
146  // If taken, put all things inside a list(array)
147  if (isset($current[$data['tag']][0]) and is_array($current[$data['tag']])) {
148  // If it is already an array...
149  // ...push the new element into that array.
150  $current[$data['tag']][$repeated_tag_index[$data['tag'].'_'.$data['level']]] = $result;
151 
152  if ($priority == 'tag' and $get_attributes and $attributes_data) {
153  $current[$data['tag']][$repeated_tag_index[$data['tag'].'_'.$data['level']] . '_attr'] = $attributes_data;
154  }
155  $repeated_tag_index[$data['tag'].'_'.$data['level']]++;
156  } else { //If it is not an array...
157  //...Make it an array using using the existing value and the new value
158  $current[$data['tag']] = [$current[$data['tag']],$result];
159  $repeated_tag_index[$data['tag'].'_'.$data['level']] = 1;
160  if ($priority == 'tag' and $get_attributes) {
161  if (isset($current[$data['tag'].'_attr'])) {
162  // The attribute of the last(0th) tag must be moved as well
163  $current[$data['tag']]['0_attr'] = $current[$data['tag'].'_attr'];
164  unset($current[$data['tag'].'_attr']);
165  }
166 
167  if ($attributes_data) {
168  $current[$data['tag']][$repeated_tag_index[$data['tag'].'_'.$data['level']] . '_attr'] = $attributes_data;
169  }
170  }
171  // 0 and 1 index is already taken
172  $repeated_tag_index[$data['tag'].'_'.$data['level']]++;
173  }
174  }
175  } elseif ($data['type'] == 'close') {
176  // End of tag '</tag>'
177  $current = &$parent[$data['level'] - 1];
178  }
179  }
180 
181  return $xml_array;
182  }
183 }
static xml2array($contents, $get_attributes=1, $priority='tag')
Transform a xml document to an array.
Definition: class_xml.inc:43
This class contains all the function needed to manage xml files.
Definition: class_xml.inc:32