88f3fc988a557dc9a631ed6e77827de2c3ed25a3
[atutor.git] / mods / phpdoc / PHPDoc / xmlreader / PhpdocXMLReader.php
1 <?php\r
2 /**\r
3 * Reads XML documents into a multi dimensional Array.\r
4 *\r
5 * @version $Id: PhpdocXMLReader.php,v 1.2 2000/12/03 22:37:38 uw Exp $\r
6 */\r
7 class PhpdocXMLReader extends PhpdocObject {\r
8         \r
9         /**\r
10         * PHPDocFileHandler object.\r
11         *\r
12         * @var  object PhpdocFileHandler\r
13         * @see  createFileHandler()\r
14         */\r
15         var $filehandler; \r
16 \r
17         /**\r
18         * Values array from xml_parse_into_struct().\r
19         *\r
20         * @var  array\r
21         * @see  parse(), stripCloseFromStructvalues(), importXML()\r
22         */\r
23         var $structvalues = array();\r
24         \r
25         /**\r
26         * Parses a given XML file and returns the data as a hash.\r
27         * \r
28         * Please do not ask me for a in detail explanation of how it is done,\r
29         * the documentation is in the source...\r
30         *\r
31         * @param        string  $filename Name of the xml document\r
32         * @access       public\r
33         * @throws PhpdocError\r
34         * @see  importXML()\r
35         */      \r
36         function parse($filename) {\r
37         \r
38                 if (""==$filename) {\r
39                         $this->err[] = new PhpdocError("No filename given.", __FILE__, __LINE__);\r
40                         return array();\r
41                 }\r
42                 \r
43                 $parser = @xml_parser_create();\r
44                 if (!$parser) {\r
45                         $this->err = PhpdocError("Can't create a XML Parser.", __FILE__, __LINE__);\r
46                         return array();\r
47                 }\r
48                 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);\r
49                 \r
50                 $this->createFileHandler();\r
51                 $xml = $this->filehandler->getFile($filename);\r
52 \r
53                 $values = array();\r
54                 $index  = array();\r
55                 xml_parse_into_struct($parser, $xml, &$values, &$index);\r
56                 \r
57                 xml_parser_free($parser);\r
58 \r
59                 $this->structvalues = $values;\r
60                 $this->stripCloseFromStructvalues();\r
61                 list($data, $last) = $this->importXML();\r
62                 $this->structvalues = array();\r
63                 \r
64                 return $data;\r
65         } // end func parse\r
66 \r
67         /**\r
68         * Creates a PhpdocFileHandler object and saves it to $filehandler if it does not already exist.\r
69         *\r
70         * @see  $filehandler\r
71         */      \r
72         function createFilehandler() {\r
73         \r
74                 if (!isset($this->filehandler))\r
75                         $this->filehandler = new PhpdocFileHandler;\r
76                         \r
77         } // end func createFilehandler\r
78         \r
79         /**\r
80         * Strips all values out of the xml_parse_intro_struct() values array with the type "open".\r
81         *\r
82         * @see  $structvalues \r
83         */\r
84         function stripCloseFromStructvalues() {\r
85                 \r
86                 $values = array();\r
87                 \r
88                 reset($this->structvalues);\r
89                 while (list($k, $v) = each($this->structvalues))\r
90                         if ("close" != $v["type"])\r
91                                 $values[] = $v;\r
92                                 \r
93                 $this->structvalues = $values;\r
94         } // end func stripCloseFromStructvalues\r
95          \r
96         /**\r
97         * Converts an xml_parse_into_struct value array to an array that's simmilar to phpdocs internal arrays.\r
98         *\r
99         * Well, don't ask me to explain this hack. Just take it as it. For those who want to unterstand and optimize\r
100         * it:\r
101         *  - PHP3 compatibility is a must\r
102         *  - no XML DOM\r
103         *  - no eval(), this can't be optimized by the compiler\r
104         *\r
105         * @param        integer \r
106         * @param        integer\r
107         * @return       array   $data[0] = daten, $data[1] = some index value used for the recursion\r
108         * @see          addToArray()\r
109         */\r
110         function importXML($start = 0, $allowed_level = 1) {\r
111                 \r
112                 $data = array();\r
113                 $last = 0;\r
114                 \r
115                 for ($i=$start; $i<count($this->structvalues); $i++) {\r
116                         if ($allowed_level != $this->structvalues[$i]["level"]) \r
117                                 break;\r
118                         \r
119                         $value          = (isset($this->structvalues[$i]["value"])) ? $this->structvalues[$i]["value"] : "";\r
120                         $attribs        = (isset($this->structvalues[$i]["attributes"])) ? $this->structvalues[$i]["attributes"] : "";\r
121                         $tag                    = $this->structvalues[$i]["tag"];\r
122 \r
123                         if ("open" == $this->structvalues[$i]["type"]) {\r
124 \r
125                                 list($inner, $next) = $this->importXML($i+1, $this->structvalues[$i]["level"]+1);\r
126                                 \r
127                                 // append the inner data to the current one\r
128                                 $data                           = $this->addToArray($data, $tag, $value, $attribs, $inner);\r
129                                 \r
130                                 // skip some entries in $this->structvalues\r
131                                 $i = $next;\r
132                                 \r
133                         } else {\r
134                         \r
135                                 // same level, append to the array\r
136                                 $data = $this->addToArray($data, $tag, $value, $attribs);\r
137                                 \r
138                         }\r
139                         \r
140                         // remember the last index in $this->structvalues we've worked on\r
141                         $last = $i;\r
142                 }\r
143                 \r
144                 return array($data, $last);\r
145         } // end func importXML\r
146         \r
147         /**\r
148         * Appends some values to an array\r
149         * Well, don't ask me; just improve it with the remarks on buildXMLResult()\r
150         * @param        array\r
151         * @param        string\r
152         * @param        string  \r
153         * @param        array\r
154         * @param        array\r
155         * @return       array $target\r
156         */\r
157         function addToArray($target, $key, $value="", $attributes = "", $inner = "") {\r
158 \r
159                 if (!isset($target[$key]["value"]) && !isset($target[$key][0])) {\r
160         \r
161                         if (""!=$inner)\r
162                                 $target[$key] = $inner;\r
163 \r
164                         if (""!=$attributes) {\r
165                                 reset($attributes);\r
166                                 while (list($k, $v) = each($attributes))\r
167                                         $target[$key][$k] = $this->xmldecode($v);\r
168                         }\r
169                                 \r
170                         $target[$key]["value"] = $this->xmldecode($value);\r
171                 \r
172                 } else {\r
173         \r
174                         if (!isset($target[$key][0])) {\r
175                 \r
176                                 $oldvalue = $target[$key];\r
177                                 $target[$key] = array();\r
178                                 $target[$key][0] = $oldvalue;\r
179                         \r
180                                 if ("" != $inner)\r
181                                         $target[$key][1] = $inner;\r
182 \r
183                                 if ("" != $attributes) {\r
184                                         reset($attributes);\r
185                                         while (list($k, $v)=each($attributes))\r
186                                                 $target[$key][1][$k] = $this->xmldecode($v);\r
187                                 }\r
188                                 \r
189                                 $target[$key][1]["value"] = $this->xmldecode($value);\r
190                                 \r
191                         } else {\r
192                                 \r
193                                 $index = count($target[$key]);\r
194                                 \r
195                                 if ("" != $inner)\r
196                                         $target[$key][$index] = $inner;\r
197 \r
198                                 if (""!=$attributes) {\r
199                                         reset($attributes);\r
200                                         while (list($k, $v) = each($attributes))\r
201                                                 $target[$key][$index][$k] = $this->xmldecode($v);\r
202                                 }\r
203                                 \r
204                                 $target[$key][$index]["value"] = $this->xmldecode($value);\r
205 \r
206                         }\r
207 \r
208                 }\r
209         \r
210                 return $target;\r
211         } // end func addToArray\r
212         \r
213         /**\r
214         * Replaces some basic entities with their character counterparts.\r
215         * \r
216         * @param        string  String to decode\r
217         * @return       string  Decoded string\r
218         */\r
219         function xmldecode($value) {\r
220                 #return preg_replace( array("@&lt;@", "@&gt;@", "@&apos;@", "@&quot;@", "@&amp;@"), array("<", ">", "'", '"', "&"), $value);\r
221                 return utf8_decode(preg_replace( array("@&lt;@", "@&gt;@", "@&apos;@", "@&quot;@", "@&amp;@"), array("<", ">", "'", '"', "&"), $value));\r
222         } // end func xmldecode\r
223 \r
224 } // end class PhpdocXMLReader\r
225 ?>