source: extensions/edit_gmaps/admin/include/XML.php @ 20035

Last change on this file since 20035 was 20035, checked in by cljosse, 11 years ago

[extensions] edit_gmaps Minor corrections

File size: 15.0 KB
Line 
1<?php
2
3/******************************************************************************
4*
5* Filename:     XML.php
6*
7* Description:  Provides functions for parsing and constructing XML information
8*
9* Author:      Evan Hunter
10*
11* Date:         27/7/2004
12*
13* Project:      JPEG Metadata
14*
15* Revision:     1.10
16*
17* Changes:      1.00 -> 1.10 : Changed read_xml_array_from_text to fix problem that
18*                              caused the whitespace (especially newlines) to be
19*                              destroyed when converting xml text to an xml array
20*
21* URL:          http://electronics.ozhiker.com
22*
23* License:      This file is part of the PHP JPEG Metadata Toolkit.
24*
25*               The PHP JPEG Metadata Toolkit is free software; you can
26*               redistribute it and/or modify it under the terms of the
27*               GNU General Public License as published by the Free Software
28*               Foundation; either version 2 of the License, or (at your
29*               option) any later version.
30*
31*               The PHP JPEG Metadata Toolkit is distributed in the hope
32*               that it will be useful, but WITHOUT ANY WARRANTY; without
33*               even the implied warranty of MERCHANTABILITY or FITNESS
34*               FOR A PARTICULAR PURPOSE.  See the GNU General Public License
35*               for more details.
36*
37*               You should have received a copy of the GNU General Public
38*               License along with the PHP JPEG Metadata Toolkit; if not,
39*               write to the Free Software Foundation, Inc., 59 Temple
40*               Place, Suite 330, Boston, MA  02111-1307  USA
41*
42*               If you require a different license for commercial or other
43*               purposes, please contact the author: evan@ozhiker.com
44*
45******************************************************************************/
46
47include_once INCLUDE_PATH.'Unicode.php';          // Unicode is required as XML is always Unicode encoded
48
49
50/******************************************************************************
51*
52* Function:     read_xml_array_from_text
53*
54* Description:  Parses a string containing XML, and returns the resulting
55*               tree structure array, which contains all the XML information.
56*               Note: White space and comments in the XML are ignored
57*               Note: All text information contained in the tree structure
58*                     is encoded as Unicode UTF-8. Hence text will appear as
59*                     normal ASCII except where there is an extended character.
60*
61* Parameters:   xmltext - a string containing the XML to be parsed
62*
63* Returns:      output - the tree structure array containing the XML information
64*               FALSE - if an error occured
65*
66******************************************************************************/
67
68function read_xml_array_from_text( $xmltext )
69{
70        // Check if there actually is any text to parse
71        if ( trim( $xmltext ) == "" )
72        {
73                return FALSE;
74        }
75
76        // Create an instance of a xml parser to parse the XML text
77        $xml_parser = xml_parser_create( "UTF-8" );
78
79
80        // Change: Fixed problem that caused the whitespace (especially newlines) to be destroyed when converting xml text to an xml array, as of revision 1.10
81
82        // We would like to remove unneccessary white space, but this will also
83        // remove things like newlines (&#xA;) in the XML values, so white space
84        // will have to be removed later
85        if ( xml_parser_set_option($xml_parser,XML_OPTION_SKIP_WHITE,0) == FALSE )
86        {
87                // Error setting case folding - destroy the parser and return
88                xml_parser_free($xml_parser);
89                return FALSE;
90        }
91
92        // to use XML code correctly we have to turn case folding
93        // (uppercasing) off. XML is case sensitive and upper
94        // casing is in reality XML standards violation
95        if ( xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0) == FALSE )
96        {
97                // Error setting case folding - destroy the parser and return
98                xml_parser_free($xml_parser);
99                return FALSE;
100        }
101
102        // Parse the XML text into a array structure
103        if ( xml_parse_into_struct($xml_parser, $xmltext, $vals, $index) == 0 )
104        {
105                // Error Parsing XML - destroy the parser and return
106                xml_parser_free($xml_parser);
107                return FALSE;
108        }
109
110        // Destroy the xml parser
111        xml_parser_free($xml_parser);
112
113
114        // Change: Fixed problem that caused the whitespace (especially newlines) to be destroyed when converting xml text to an xml array, as of revision 1.10
115
116        // Since the xml was processed with whitespace enabled, it will have many values which are
117        // only whitespace. These need to be removed to make a sensible array.
118
119        $newvals = array( );
120
121        // Cycle through each of the items
122        foreach( $vals as $valno => $val )
123        {
124                // If the item has a whitespace only value, remove it
125                if ( ( array_key_exists( 'value', $val ) ) && (trim( $val[ 'value' ] ) == "" ) )
126                {
127                        unset( $val[ 'value' ] );
128                }
129                // If the item has a value (which will be non blank now) or is of type other than cdata, add it to the new array
130                if ( ( $val[ 'type' ] != 'cdata' ) || ( array_key_exists( 'value', $val ) ) )
131                {
132                        $newvals[] = $val;
133                }
134
135        }
136
137        // The xml_parse_into_struct function returns a flat version
138        // of the XML data, where each tag has a level number attached.
139        // This is very difficult to work with, so it needs to be
140        // converted to a tree structure before being returned
141         $i=0;
142        return xml_get_children($newvals, $i);
143
144}
145
146/******************************************************************************
147* End of Function:     read_xml_array_from_text
148******************************************************************************/
149
150
151
152
153
154/******************************************************************************
155*
156* Function:     write_xml_array_to_text
157*
158* Description:  Takes a tree structure array (in the same format as returned
159*               by read_xml_array_from_text, and constructs a string containing
160*               the equivalent XML. This function is recursive, and produces
161*               XML which has correct indents.
162*               Note: All text information contained in the tree structure
163*                     can be either 7-bit ASCII or encoded as Unicode UTF-8,
164*                     since UTF-8 passes 7-bit ASCII text unchanged.
165*
166* Parameters:   xmlarray - the tree structure array containing the information to
167*                          be converted to XML
168*               indentlevel - the indent level of the top level tags (usually zero)
169*
170* Returns:      output - the string containing the equivalent XML
171*               FALSE - if an error occured
172*
173******************************************************************************/
174
175function write_xml_array_to_text( $xmlarray, $indentlevel )
176{
177        // Create a string to receive the XML
178        $output_xml_text = "";
179
180
181        // Cycle through each xml element at this level
182        foreach ($xmlarray as $xml_elem)
183        {
184
185                // Add the indent, then the cleaned tag name to the output
186                $output_xml_text .= str_repeat ( " ", $indentlevel ) . "<" . xml_UTF8_clean( $xml_elem['tag'] );
187
188                // Check if there are any attributes for this tag
189                if (array_key_exists('attributes',$xml_elem))
190                {
191                        // There are attributes
192                        // Cycle through each attribute for this tag
193                        foreach ($xml_elem['attributes'] as  $xml_attr_name => $xml_attr_val)
194                        {
195                                // Add the cleaned attribute name, and cleaned attribute value to the output
196                                $output_xml_text .= " ". xml_UTF8_clean( $xml_attr_name ) ." ='" .  xml_UTF8_clean( $xml_attr_val ) ."'";
197                        }
198                }
199
200                // Add the 'greater-than' to close this tag to the output
201                $output_xml_text .= ">";
202
203                // Check if this element has any text inside it.
204                if (array_key_exists('value',$xml_elem) )
205                {
206                        // There is text for this element - clean it and add it to the output
207                        $output_xml_text .=  xml_UTF8_clean( $xml_elem['value'] );
208                }
209
210                // Check if there are any lower levels contained by this element
211                if (array_key_exists('children',$xml_elem) )
212                {
213                        // There are sub-elements for this element
214
215                        // Add a newline to the output, so the sub-elements start on a fresh line
216                        $output_xml_text .= "\n";
217
218                        // Recursively call this function to output the sub-elements, and add the result to the output
219                        $output_xml_text .= write_xml_array_to_text( $xml_elem['children'], $indentlevel + 1 );
220
221                        // Add an indent to the output for the closing tag, since we are on a new line due to the sub-elements
222                        $output_xml_text .= str_repeat ( " ", $indentlevel );
223                }
224
225                // Add the cleaned closing tag to the output
226                $output_xml_text .= "</" .xml_UTF8_clean($xml_elem['tag']) . ">\n";
227        }
228
229        // Return the XML text
230        return $output_xml_text;
231}
232
233/******************************************************************************
234* End of Function:     write_xml_array_to_text
235******************************************************************************/
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259/******************************************************************************
260*
261*         INTERNAL FUNCTIONS
262*
263******************************************************************************/
264
265
266
267
268
269
270/******************************************************************************
271*
272* Internal Function:     xml_get_children
273*
274* Description:  Used by the read_xml_array_from_text function.
275*               This function recursively converts the values retrieved from
276*               the xml_parse_into_struct function into a tree structure array,
277*               which is much more useful and easier to use.
278*
279* Parameters:   input_xml_array - the flat array of XML elements retrieved
280*                                 from xml_parse_into_struct
281*               $item_num - the number of the element at which the conversion
282*                           should start (usually zero when called from another
283*                           function, this is used for recursion)
284*
285* Returns:      children - the tree structure array containing XML elements
286*               FALSE - if an error occured
287*
288******************************************************************************/
289
290function xml_get_children( &$input_xml_array, &$item_num )
291{
292
293        // Make an array to receive the output XML tree structure
294        $children = array();
295
296
297        // Cycle through all the elements of the input XML array
298        while ( $item_num < count( $input_xml_array ) )
299        {
300                // Retrieve the current array element
301                $v = &$input_xml_array[ $item_num++ ];
302
303                // Check what type of XML array element this is, and process accordingly
304
305                switch ( $v['type'] )
306                {
307                        case 'cdata':     // This is a non parsed Character Data tag
308                        case 'complete':  // This is a pair of XML matching tags possibly with text (but no tags) inside
309                                $children[] = xml_get_child( $v );
310                                break;
311
312                        case 'open':      // This is a single opening tag
313                                // Recursively get the children for this opening tag
314                                $children[] = xml_get_child( $v, xml_get_children( $input_xml_array, $item_num ) );
315                                break;    // This is a single opening tag
316
317                        case 'close':     // This is a single closing tag
318                                break 2;  // leave "while" loop (and the function)
319                }
320        }
321
322        // Return the results
323        return $children;
324}
325
326/******************************************************************************
327* End of Function:     xml_get_children
328******************************************************************************/
329
330
331/******************************************************************************
332*
333* Internal Function:     xml_get_child
334*
335* Description:  Used by the xml_get_children function.
336*               Takes an element from an array provided by xml_parse_into_struct
337*               and returns an element for a tree structure array
338*
339* Parameters:   input_xml_item - the item from the array provided by xml_parse_into_struct
340*               children - an array of sub-elements to be added to the tree
341*                          structure array. Null or missing value indicate no
342*                          sub-elements are to be added.
343*
344* Returns:      child - the element for a tree structure array
345*               FALSE - if an error occured
346*
347******************************************************************************/
348
349function xml_get_child( &$input_xml_item, $children = NULL )
350{
351        // Create an array to receive the child structure
352        $child = array();
353
354        // If the input item has the 'tag' element set, copy it to the child
355        if ( isset( $input_xml_item['tag'] ) )
356        {
357                $child['tag'] = $input_xml_item['tag'] ;
358        }
359
360        // If the input item has the 'value' element set, copy it to the child
361        if ( isset( $input_xml_item['value'] ) )
362        {
363                $child['value'] = $input_xml_item['value'] ;
364        }
365
366        // If the input item has the 'attributes' element set, copy it to the child
367        if ( isset( $input_xml_item['attributes'] ) )
368        {
369                $child['attributes'] = $input_xml_item['attributes'];
370        }
371
372        // If children have been specified, add them to the child
373        if ( is_array( $children ) )
374        {
375                $child['children'] = $children;
376        }
377
378        // Return the child structure
379        return $child;
380}
381
382/******************************************************************************
383* End of Function:     xml_get_children
384******************************************************************************/
385
386
387
388
389
390
391
392
393
394
395
396
397?>
Note: See TracBrowser for help on using the repository browser.