xml_parser._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2004 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * $Id: xml_parser.pike,v 1.1 2008/03/31 13:39:57 exodusd Exp $
18  */
19  inherit Node;
20 #include <macros.h>
21 //! this is a structure to make accessing Parser.XML.Node(s) easier.
22 class xml_parser {
23 public:
24 
25 
26 
27 
28 import xmlDom;
29 
30 string node_to_str(object n);
31 
32 
33 
34 class NodeXML
35 {
36 public:
37 
38  mapping pi = ([ ]); // processing instructions;
39 };
40 
41 
42 
43 /**
44  * Parse given data using the Parser.XML.Tree module.
45  *
46  * @param string data - the xml data to parse.
47  * @return NodeXML structure described by its root-node.
48  */
49 NodeXML parse_data(string data)
50 {
51  return parse(data);
52 }
53 
54 /**
55  * Converts a node of an XML Tree to a string.
56  *
57  * @param NodeXML ann - the node to convert.
58  * @return string representation of the Node and it children recursively.
59  * @see
60  */
61 string node_to_str(NodeXML ann)
62 {
63  string res = "";
64  string attr;
65 
66  res = "<"+ann->name;
67  foreach(indices(ann->attributes), attr) {
68  if ( attr != ann->name )
69  res += " " + attr + "=\""+ann->attributes[attr]+"\"";
70  }
71  res += ">"+ann->data;
72  foreach(ann->children, NodeXML child) {
73  res += "<"+child->name;
74  foreach(indices(child->attributes), attr) {
75  if ( attr != child->name )
76  res += " " + attr + "=\""+child->attributes[attr]+"\"";
77  }
78  res += ">" + child->data + children_to_str(child->children)+
79  "</"+child->name+">\n";
80  }
81  res += "</"+ann->name+">\n";
82  return res;
83 }
84 
85 /**
86  * Some conversion function I forgot where it is used at all.
87  *
88  * @param array annotations - an array of annotations to convert
89  * @return a string representation of the annotations.
90  */
91 string children_to_str(array annotations)
92 {
93  string res = "";
94  if ( !arrayp(annotations) )
95  return res;
96 
97  foreach(annotations, NodeXML ann) {
98  res += node_to_str(ann);
99  }
100  return res;
101 }
102 
103 /**
104  * Convert some annotations to a string representation by using the
105  * children_to_str function. Remember annotations can be annotated again!
106  *
107  * @param array annotations - the annotations to convert.
108  * @return string representation of the annotations.
109  * @see children_to_str
110  */
111 string convert_annotations(array annotations)
112 {
113  string res = "";
114  foreach(annotations, NodeXML ann) {
115  res += children_to_str(ann->children);
116  }
117  return res;
118 }
119 
120 /**
121  * Display the structure of a XML Tree given by NodeXML node.
122  *
123  * @param NodeXML node - the node, for example the root-node of the tree.
124  * @return just writes the structure to stderr.
125  */
126 void display_structure(NodeXML node, void|int depth)
127 {
128  for ( int i = 0 ; i < depth; i++ )
129  werror("\t");
130  werror(node->name+":"+node->data+"\n");
131  foreach(node->children, NodeXML n) {
132  display_structure(n, depth+1);
133  }
134 }
135 
136 /**
137  * Create a mapping from an XML Tree.
138  *
139  * @param NodeXML n - the root-node to transform to a mapping.
140  * @return converted mapping.
141  */
142 mapping xmlMap(NodeXML n)
143 {
144  mapping res = ([ ]);
145  foreach ( n->children, NodeXML children) {
146  if ( children->name == "member" ) {
147  mixed key,value;
148  foreach(children->children, object o) {
149 
150  if ( o->name == "key" )
151  key = unserialize(o->children[0]);
152  else if ( o->name == "value" )
153  value = unserialize(o->children[0]);
154  }
155  res[key] = value;
156  }
157  }
158  return res;
159 }
160 
161 /**
162  * Create an array with the childrens of the given Node.
163  *
164  * @param NodeXML n - the current node to unserialize.
165  * @return Array with unserialized childrens.
166  */
167 array xmlArray(NodeXML n)
168 {
169  array res = ({ });
170  foreach ( n->children, NodeXML children) {
171  res += ({ unserialize(children) });
172  }
173  return res;
174 }
175 
176 /**
177  * Create some data structure from an XML Tree.
178  *
179  * @param NodeXML n - the root-node of the XML Tree to unserialize.
180  * @return some data structure describing the tree.
181  */
182 mixed unserialize(NodeXML n)
183 {
184  switch ( n->name ) {
185  case "struct":
186  return xmlMap(n);
187  break;
188  case "array":
189  return xmlArray(n);
190  break;
191  case "int":
192  return (int)n->data;
193  break;
194  case "float":
195  return (float)n->data;
196  break;
197  case "string":
198  return n->data;
199  break;
200  }
201  return -1;
202 }
203 
204 
205 {
206  string xml = "<?xml version='1.0'?><a>1<b>2</b>3<c a='1'>4</c></a>";
207  object node = parse_data(xml);
208  object n = node->get_node("/a/b");
209  if ( !objectp(n) || n->data != "2" )
210  error("Failed to resolve xpath expression.");
211  n->replace_node("<huh/>");
212  if ( node->get_xml()!= "<a >13<huh ></huh>\n<c a='1' >4</c>\n</a>\n" )
213  error("replacing of <b/> didnt work !\nResult is:"+node->get_xml());
214 
215  // error testing
216  xml = "<a><b/>";
217 
218  mixed err = catch(parse_data(xml));
219  if ( err == 0 )
220  error("Wrong xml code does not throw error.\n");
221 
222  xml = "<a><b test=1/></a>";
223  err = catch(parse_data(xml));
224  if ( err == 0 )
225  error("Wrong xml code does not throw error.\n");
226 
227  return n;
228 }
229 
230 
231 
232 };