File: class_xml.inc

package info (click to toggle)
fusiondirectory 1.2.3-4%2Bdeb10u1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 33,140 kB
  • sloc: php: 45,518; pascal: 3,700; perl: 2,026; xml: 1,521; sh: 137; makefile: 22
file content (174 lines) | stat: -rw-r--r-- 6,679 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<?php
/*
  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
  Copyright (C) 2003-2010  Cajus Pollmeier
  Copyright (C) 2011-2016  FusionDirectory

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/

/*!
 * \file class_xml.inc
 * Source code for class xml
 */

/*!
 * \brief This class contains all the function needed to manage xml
 * files
 */
class xml {
  /*!
   * \brief Transform a xml document to an array
   *
   * \param $contents Contents
   *
   * \param integer $get_attributes Initialized at 1
   *
   * \param string $priority Initialized at 'tag'
   */
  static function xml2array($contents, $get_attributes = 1, $priority = 'tag')
  {
    if (!$contents) {
      return array();
    }

    if (!function_exists('xml_parser_create')) {
      trigger_error('xml_parser_create function does not exists');
      return array();
    }

    //Get the XML parser of PHP - PHP must have this module for the parser to work
    $parser = xml_parser_create('');
    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
    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
    xml_parse_into_struct($parser, trim($contents), $xml_values);
    xml_parser_free($parser);

    if (!$xml_values) {
      return;//Hmm...
    }

    //Initializations
    $xml_array    = array();

    $current = &$xml_array; //Refference

    //Go through the tags.
    $repeated_tag_index = array();//Multiple tags with same name will be turned into an array
    foreach ($xml_values as $data) {
      unset($attributes, $value);//Remove existing values, or there will be trouble

      //This command will extract these variables into the foreach scope
      // tag(string), type(string), level(int), attributes(array).
      extract($data);//We could use the array by itself, but this cooler.

      $result = array();
      $attributes_data = array();

      if (isset($value)) {
        if ($priority == 'tag') {
          $result = $value;
        } else {
          //Put the value in a assoc array if we are in the 'Attribute' mode
          $result['value'] = $value;
        }
      }

      //Set the attributes too.
      if (isset($attributes) and $get_attributes) {
        foreach ($attributes as $attr => $val) {
          if ($priority == 'tag') {
            $attributes_data[$attr] = $val;
          } else {
            //Set all the attributes in a array called 'attr'
            $result['attr'][$attr] = $val;
          }
        }
      }

      //See tag status and do the needed.
      if ($type == "open") {//The starting of the tag '<tag>'
        $parent[$level - 1] = &$current;
        if (!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag
          $current[$tag] = $result;
          if ($attributes_data) {
            $current[$tag. '_attr'] = $attributes_data;
          }
          $repeated_tag_index[$tag.'_'.$level] = 1;

          $current = &$current[$tag];

        } else { //There was another element with the same tag name

          if (isset($current[$tag][0])) {//If there is a 0th element it is already an array
            $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
            $repeated_tag_index[$tag.'_'.$level]++;
          } else {//This section will make the value an array if multiple tags with the same name appear together
            $current[$tag] = array($current[$tag],$result);//This will combine the existing item and the new item together to make an array
            $repeated_tag_index[$tag.'_'.$level] = 2;

            if (isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
              $current[$tag]['0_attr'] = $current[$tag.'_attr'];
              unset($current[$tag.'_attr']);
            }
          }
          $last_item_index  = $repeated_tag_index[$tag.'_'.$level] - 1;
          $current          = &$current[$tag][$last_item_index];
        }

      } elseif ($type == "complete") { //Tags that ends in 1 line '<tag />'
        //See if the key is already taken.
        if (!isset($current[$tag])) { //New Key
          $current[$tag]                        = $result;
          $repeated_tag_index[$tag.'_'.$level]  = 1;
          if ($priority == 'tag' and $attributes_data) {
            $current[$tag. '_attr'] = $attributes_data;
          }
        } else { //If taken, put all things inside a list(array)
          if (isset($current[$tag][0]) and is_array($current[$tag])) {//If it is already an array...
            // ...push the new element into that array.
            $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;

            if ($priority == 'tag' and $get_attributes and $attributes_data) {
                $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
            }
            $repeated_tag_index[$tag.'_'.$level]++;

          } else { //If it is not an array...
            $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
            $repeated_tag_index[$tag.'_'.$level] = 1;
            if ($priority == 'tag' and $get_attributes) {
              if (isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
                $current[$tag]['0_attr'] = $current[$tag.'_attr'];
                unset($current[$tag.'_attr']);
              }

              if ($attributes_data) {
                $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
              }
            }
            $repeated_tag_index[$tag.'_'.$level]++; //0 and 1 index is already taken
          }
        }
      } elseif ($type == 'close') { //End of tag '</tag>'
        $current = &$parent[$level - 1];
      }
    }

    return $xml_array;
  }

}