cf1dee3ba10890216138245ebdec8fd73abce6af
[moodle.git] / lib / xmlize.php
1 <?php
3 /**
4  * xmlize.php - xmlize() is by Hans Anderson, {@link http://www.hansanderson.com/contact/}
5  *
6  * Ye Ole "Feel Free To Use it However" License [PHP, BSD, GPL].
7  * some code in xml_depth is based on code written by other PHPers
8  * as well as one Perl script.  Poor programming practice and organization
9  * on my part is to blame for the credit these people aren't receiving.
10  * None of the code was copyrighted, though.
11  *
12  * @package moodlecore
13  * @author Hans Anderson
14  * @version This is a stable release, 1.0.  I don't foresee any changes, but you
15  * might check {@link http://www.hansanderson.com/php/xml/} to see
16  * @copyright Hans Anderson
17  * @license Feel Free To Use it However
18  */
20 /**
21  * Create xml formatted output from an array.
22  *
23  * usage:<br>
24  * <code>
25  * $xml = xmlize($array);
26  * </code>
27  * See the function {@link traverse_xmlize()} for information about the
28  * structure of the array, it's much easier to explain by showing you.
29  * Be aware that the array is somewhat tricky.  I use xmlize all the time,
30  * but still need to use {@link traverse_xmlize()} quite often to show me the structure!
31  *
32  * THIS IS A PHP 5 VERSION:
33  *
34  * This modified version basically has a new optional parameter
35  * to specify an OUTPUT encoding. If not specified, it defaults to UTF-8.
36  * I recommend you to read this PHP bug. There you can see how PHP4, PHP5.0.0
37  * and PHP5.0.2 will handle this.
38  * {@link http://bugs.php.net/bug.php?id=29711}
39  * Ciao, Eloy :-)
40  *
41  *
42  * @author Hans Anderson
43  * @param array $data The array to be converted
44  * @param int $WHITE  If set to 1 allows the parser to skip "space" characters in xml document. Default is 1
45  * @param string $encoding Specify an OUTPUT encoding. If not specified, it defaults to UTF-8.
46  * @return array
47  */
48 function xmlize($data, $WHITE=1, $encoding='UTF-8') {
50     $data = trim($data);
51     $vals = $index = $array = array();
52     $parser = xml_parser_create($encoding);
53     xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
54     xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, $WHITE);
55     xml_parse_into_struct($parser, $data, $vals, $index);
56     xml_parser_free($parser);
58     $i = 0;
59     
60     if (empty($vals)) {
61         // XML file is invalid or empty, return false
62         return false;
63     }
65     $tagname = $vals[$i]['tag'];
66     if ( isset ($vals[$i]['attributes'] ) )
67     {
68         $array[$tagname]['@'] = $vals[$i]['attributes'];
69     } else {
70         $array[$tagname]['@'] = array();
71     }
73     $array[$tagname]["#"] = xml_depth($vals, $i);
76     return $array;
77 }
79 /**
80  * @internal You don't need to do anything with this function, it's called by
81  * xmlize. It's a recursive function, calling itself as it goes deeper
82  * into the xml levels.  If you make any improvements, please let me know.
83  * @access private
84  */
85 function xml_depth($vals, &$i) {
86     $children = array();
88     if ( isset($vals[$i]['value']) )
89     {
90         array_push($children, $vals[$i]['value']);
91     }
93     while (++$i < count($vals)) {
95         switch ($vals[$i]['type']) {
97            case 'open':
99                 if ( isset ( $vals[$i]['tag'] ) )
100                 {
101                     $tagname = $vals[$i]['tag'];
102                 } else {
103                     $tagname = '';
104                 }
106                 if ( isset ( $children[$tagname] ) )
107                 {
108                     $size = sizeof($children[$tagname]);
109                 } else {
110                     $size = 0;
111                 }
113                 if ( isset ( $vals[$i]['attributes'] ) ) {
114                     $children[$tagname][$size]['@'] = $vals[$i]["attributes"];
116                 }
118                 $children[$tagname][$size]['#'] = xml_depth($vals, $i);
120             break;
123             case 'cdata':
124                 array_push($children, $vals[$i]['value']);
125             break;
127             case 'complete':
128                 $tagname = $vals[$i]['tag'];
130                 if( isset ($children[$tagname]) )
131                 {
132                     $size = sizeof($children[$tagname]);
133                 } else {
134                     $size = 0;
135                 }
137                 if( isset ( $vals[$i]['value'] ) )
138                 {
139                     $children[$tagname][$size]["#"] = $vals[$i]['value'];
140                 } else {
141                     $children[$tagname][$size]["#"] = '';
142                 }
144                 if ( isset ($vals[$i]['attributes']) ) {
145                     $children[$tagname][$size]['@']
146                                              = $vals[$i]['attributes'];
147                 }
149             break;
151             case 'close':
152                 return $children;
153             break;
154         }
156     }
158         return $children;
164 /**
165  * This helps you understand the structure of the array {@link xmlize()} outputs
166  *
167  * Function by acebone@f2s.com, a HUGE help!<br>
168  * Usage:<br>
169  * <code>
170  * traverse_xmlize($xml, 'xml_');
171  * print '<pre>' . implode("", $traverse_array . '</pre>';
172  * </code>
173  * @author acebone@f2s.com
174  * @param array $array ?
175  * @param string $arrName ?
176  * @param int $level ?
177  * @return int
178  * @todo Finish documenting this function
179  */
180 function traverse_xmlize($array, $arrName = 'array', $level = 0) {
182     foreach($array as $key=>$val)
183     {
184         if ( is_array($val) )
185         {
186             traverse_xmlize($val, $arrName . '[' . $key . ']', $level + 1);
187         } else {
188             $GLOBALS['traverse_array'][] = '$' . $arrName . '[' . $key . '] = "' . $val . "\"\n";
189         }
190     }
192     return 1;
196 ?>