xml_simple.php 5.13 KB
Newer Older
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
<?
/* xml-simple.php

Simple XML Parser for PHP by Rogers Cadenhead, derived from
original code by Jim Winstead Jr.

Version 1.01
Web: http://www.cadenhead.org/workbench/xml-simple
   
Copyright (C) 2005 Rogers Cadenhead

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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */

if (__FILE__ == $PATH_TRANSLATED) {
    header("Status: 403 Forbidden");
    exit();
}

// a PHP class library that parses XML data
class xml_simple {
    /* an array that holds parsed XML data as either name-value pairs (for character data) or           arrays (for subelements) */
    var $tree = array();
    var $force_to_array = array();
    // a descriptive error message, if the class fails to execute successfully
    var $error = null;

    // Create the XML parser that will read XML data formatted with the specified encoding
    function xml_simple($encoding = 'UTF-8') {
        $this->parser = xml_parser_create($encoding);
42
        xml_set_object($this->parser, $this);
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
        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
        xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1);
        xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
        xml_set_element_handler($this->parser, "start_element", "stop_element");
        xml_set_character_data_handler($this->parser, "char_data");
    }

    function force_to_array() {
        for ($i = 0; $i < func_num_args(); $i++) {
            $this->force_to_array[] = func_get_arg($i);
        }
    }

    /* Parse XML data, storing it in the instance variable; returns false if the data cannot be         parsed. */
    function parse($data) {
        $this->tree = array();

        if (!xml_parse($this->parser, $data, 1)) {
            $this->error = "xml parse error: " .
                xml_error_string(xml_get_error_code($this->parser)) .
	            " on line ".xml_get_current_line_number($this->parser);
            return false;
        }
        return $this->tree[0]["content"];
    }

    function parse_file($file) {
        $fp = @fopen($file, "r");
        if (!$fp) {
            user_error("unable to open file: '$file'");
            return false;
        }   
        while ($data = fread($fp, 4096)) {
            if (!xml_parse($this->parser, $data, feof($fp))) {
	            user_error("xml parse error: " .
	                xml_error_string(xml_get_error_code($this->parser)) .
	                " on line " . xml_get_current_line_number($this->parser));
                }
            }
            fclose($fp);
            return $this->tree[0]["content"];
        }

    function encode_as_xml($value) {
        if (is_array($value)) {
            reset($value); $out = '';
            while (list($key,$val) = each($value)) {
	            if (is_array($val) && isset($val[0])) {
	                reset($val);
	                while (list(,$item) = each($val)) {
	                    $out .= "<$key>".xml_simple::encode_as_xml($item)."</$key>";
	                }
	            } else {
	                $out .= "<$key>".xml_simple::encode_as_xml($val)."</$key>";
	            }
            }
            return $out;
        } else {
            return htmlspecialchars($value);
        }
    }

    function start_element($parser, $name, $attrs) {
        array_unshift($this->tree, array("name" => $name));
    }

    function stop_element($parser, $name) {
        if ($name != $this->tree[0]["name"]) die("incorrect nesting");
        if (count($this->tree) > 1) {
            $elem = array_shift($this->tree);
            if (isset($this->tree[0]["content"][$elem["name"]])) {
	            if (is_array($this->tree[0]["content"][$elem["name"]]) && isset($this->tree[0]["content"][$elem["name"]][0])) {
	                array_push($this->tree[0]["content"][$elem["name"]], $elem["content"]);
	            } else {
	                $this->tree[0]["content"][$elem["name"]] =
	                array($this->tree[0]["content"][$elem["name"]],$elem["content"]);
	            }
            } else {
	            if (in_array($elem["name"],$this->force_to_array)) {
	                $this->tree[0]["content"][$elem["name"]] = array($elem["content"]);
	            } else {
	                if (!isset($elem["content"])) $elem["content"] = "";
	                $this->tree[0]["content"][$elem["name"]] = $elem["content"];
	            }
            }
        }
    }

    function char_data($parser, $data) {
        # don't add a string to non-string data
        if (!is_string($this->tree[0]["content"]) && !preg_match("/\\S/", $data)) return;
        $this->tree[0]["content"] .= $data;
    }
}