1 /* $Id: router_flexml.hpp,v 1.5 2005-10-31 11:59:08 marc Exp $
2 Copyright (c) 2005, Index Data.
14 #include <libxml/xmlversion.h>
15 #include <libxml/parser.h>
16 #include <libxml/tree.h>
18 #include <boost/shared_ptr.hpp>
25 class RouterFleXML : public yp2::Router
28 RouterFleXML(std::string xmlconf)
29 : m_xmlconf(""), m_xinclude(false), m_xmlconf_doc(0)
37 = xmlParseMemory(m_xmlconf.c_str(), m_xmlconf.size());
39 parse_xml_config_dom();
44 xmlFreeDoc(m_xmlconf_doc);
49 typedef std::map<std::string, boost::shared_ptr<const yp2::filter::Base> >
51 typedef std::list<std::string> FilterIdList;
52 typedef std::map<std::string, FilterIdList > IdRouteMap ;
56 std::string m_xmlconf;
58 xmlDoc * m_xmlconf_doc;
59 IdFilterMap m_id_filter_map;
60 FilterIdList m_filter_id_list;
61 IdRouteMap m_id_route_map;
63 //boost::shared_ptr<T> s_ptr(new T(t));
66 void xml_dom_error (const xmlNode* node, std::string msg)
68 std::cerr << "ERROR: " << msg << " <"
73 void create_filter(std::string type,
74 const xmlDoc * xmldoc,
77 std::cout << "Created Filter type='" << type
78 << "' id='" << id << "'" << std::endl;
82 void parse_xml_config_dom() {
85 std::cerr << "XML configuration DOM pointer empty" << std::endl;
88 const xmlNode* root = xmlDocGetRootElement(m_xmlconf_doc);
90 if ((std::string((const char *) root->name) != "yp2")
91 || (std::string((const char *)(root->ns->href))
92 != "http://indexdata.dk/yp2/config/1")
95 "expected <yp2 xmlns=\"http://indexdata.dk/yp2/config/1\">, got ");
98 for (const struct _xmlAttr *attr = root->properties; attr; attr = attr->next)
100 if (std::string((const char *)attr->name) == "xmlns")
102 const xmlNode *val = attr->children;
103 if (std::string((const char *)val->content)
104 != "http://indexdata.dk/yp2/config/1")
106 "expected xmlns=\"http://indexdata.dk/yp2/config/1\", got ");
109 std::cout << "processing /yp2" << std::endl;
111 // process <start> node which is expected first element node
112 const xmlNode* node = jump_to_children(root, XML_ELEMENT_NODE);
113 //for (; node && node->type != XML_ELEMENT_NODE; node = node->next)
116 check_node_name(node, "start");
117 std::cout << "processing /yp2/start" << std::endl;
119 // process <filters> node which is expected second element node
120 node = jump_to_next(node, XML_ELEMENT_NODE);
121 check_node_name(node, "filters");
122 std::cout << "processing /yp2/filters" << std::endl;
124 // process <filter> nodes in next level
125 const xmlNode* node2 = jump_to_children(node, XML_ELEMENT_NODE);
126 check_node_name(node2, "filter");
128 unsigned int filter_nr = 0;
129 while(node2 && std::string((const char *)node2->name) == "filter"){
131 std::cout << "processing /yp2/filters/filter["
132 << filter_nr << "]" << std::endl;
133 node2 = jump_to_next(node2, XML_ELEMENT_NODE);
136 // process <routes> node which is expected third element node
137 node = jump_to_next(node, XML_ELEMENT_NODE);
138 check_node_name(node, "routes");
139 std::cout << "processing /yp2/routes" << std::endl;
141 // process <route> nodes in next level
142 node2 = jump_to_children(node, XML_ELEMENT_NODE);
143 check_node_name(node2, "route");
145 unsigned int route_nr = 0;
146 while(node2 && std::string((const char *)node2->name) == "route"){
148 std::cout << "processing /yp2/routes/route["
149 << route_nr << "]" << std::endl;
151 // process <filter> nodes in third level
153 = jump_to_children(node2, XML_ELEMENT_NODE);
154 check_node_name(node3, "filter");
156 unsigned int filter3_nr = 0;
157 while(node3 && std::string((const char *)node3->name) == "filter"){
160 std::cout << "processing /yp2/routes/route["
161 << route_nr << "]/filter["
162 << filter3_nr << "]" << std::endl;
164 node3 = jump_to_next(node3, XML_ELEMENT_NODE);
167 node2 = jump_to_next(node2, XML_ELEMENT_NODE);
174 const xmlNode* jump_to(const xmlNode* node, int xml_node_type){
175 for (; node && node->type != xml_node_type; node = node->next)
180 const xmlNode* jump_to_next(const xmlNode* node, int xml_node_type){
182 for (; node && node->type != xml_node_type; node = node->next)
187 const xmlNode* jump_to_children(const xmlNode* node, int xml_node_type){
188 node = node->children;
189 for (; node && node->type != xml_node_type; node = node->next)
194 void check_node_name(const xmlNode* node, std::string name){
195 if (std::string((const char *)node->name)
197 xml_dom_error(node, "expected <" + name + ">, got ");
203 void parse_xml_config_xmlreader() {
205 xmlTextReader* reader;
206 //reader->SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1);
208 //reader = xmlReaderForFile(m_xmlconf.c_str(), NULL, 0);
209 reader = xmlReaderWalker(m_xmlconf_doc);
211 if (reader == NULL) {
212 std::cerr << "failed to read XML config file "
214 << m_xmlconf << std::endl;
219 // root element processing
220 xml_progress_deep_to_element(reader);
221 if (std::string("yp2") != (const char*)xmlTextReaderConstName(reader))
222 xml_error(reader, "root element must be named <yp2>");
224 std::cout << "<" << xmlTextReaderConstName(reader);
226 //if (xmlTextReaderHasAttributes(reader))
227 //if ((!xmlTextReaderMoveToAttributeNs(reader, NULL,
228 // (const xmlChar*)"http://indexdata.dk/yp2/config/1" )))
229 if ((!xmlTextReaderMoveToFirstAttribute(reader))
230 || (! xmlTextReaderIsNamespaceDecl(reader))
231 || (std::string("http://indexdata.dk/yp2/config/1")
232 != (const char*)xmlTextReaderConstValue(reader)))
233 xml_error(reader, "expected root element <yp2> in namespace "
234 "'http://indexdata.dk/yp2/config/1'");
236 std::cout << " " << xmlTextReaderConstName(reader) << "=\""
237 << xmlTextReaderConstValue(reader) << "\">"
238 //<< xmlTextReaderIsNamespaceDecl(reader)
242 // start element processing
243 xml_progress_deep_to_element(reader);
244 if (std::string("start") != (const char*)xmlTextReaderConstName(reader)
245 || !xmlTextReaderMoveToFirstAttribute(reader)
246 || std::string("route") != (const char*)xmlTextReaderConstName(reader)
248 xml_error(reader, "start element <start route=\"route_id\"/> expected");
249 std::cout << "<start " << xmlTextReaderConstName(reader) << "=\""
250 << xmlTextReaderConstValue(reader) << "\"/>" << std::endl;
251 //<< xmlTextReaderGetAttribute(reader, (const xmlChar *)"route")
254 // filters element processing
255 xml_progress_flat_to_element(reader);
257 if (std::string("filters") != (const char*)xmlTextReaderConstName(reader)
259 xml_error(reader, "filters element <filters> expected");
261 std::cout << "<filters>" << std::endl;
264 // filter element processing
265 xml_progress_deep_to_element(reader);
266 if (std::string("filter") != (const char*)xmlTextReaderConstName(reader)
268 xml_error(reader, "filter element <filter id=\"some_id\" "
269 "type=\"some_type\"/> expected");
271 while (std::string("filter") == (const char*)xmlTextReaderConstName(reader)){
272 std::string filter_id;
273 std::string filter_type;
274 if (!xmlTextReaderMoveToFirstAttribute(reader)
275 || std::string("id") != (const char*)xmlTextReaderConstName(reader))
276 xml_error(reader, "filter element <filter id=\"some_id\" "
277 "type=\"some_type\"/> expected");
278 filter_id = (const char*)xmlTextReaderConstValue(reader);
279 if (!xmlTextReaderMoveToNextAttribute(reader)
280 || std::string("type") != (const char*)xmlTextReaderConstName(reader))
281 xml_error(reader, "filter element <filter id=\"some_id\" "
282 "type=\"some_type\"/> expected");
283 filter_type = (const char*)xmlTextReaderConstValue(reader);
284 std::cout << "<filter id=\"" << filter_id
285 << "\" type=\"" << filter_type << "\"/>"
287 xml_progress_flat_to_element(reader);
290 std::cout << "</filters>" << std::endl;
293 // routes element processing
294 // xml_progress_flat_to_element(reader);
295 if (std::string("routes") != (const char*)xmlTextReaderConstName(reader)
297 xml_error(reader, "routes element <routes> expected");
299 std::cout << "<routes>" << std::endl;
300 // route element processing
301 xml_progress_deep_to_element(reader);
302 if (std::string("route") != (const char*)xmlTextReaderConstName(reader)
304 xml_error(reader, "route element <route id=\"some_id\" "
305 "type=\"some_type\"/> expected");
306 while (std::string("route") == (const char*)xmlTextReaderConstName(reader)){
307 std::string route_id;
308 if (!xmlTextReaderMoveToFirstAttribute(reader)
309 || std::string("id") != (const char*)xmlTextReaderConstName(reader))
310 xml_error(reader, "route element <route id=\"some_id\"/> expected");
311 route_id = (const char*)xmlTextReaderConstValue(reader);
314 std::cout << "<route id=\"" << route_id << "\">" << std::endl;
315 std::cout << "</route>" << std::endl;
316 xml_progress_flat_to_element(reader);
319 std::cout << "</routes>" << std::endl;
321 std::cout << "</yp2>" << std::endl;
323 xml_debug_print(reader);
326 // freeing C xml reader libs
327 xmlFreeTextReader(reader);
329 std::cerr << "Parsing failed of XML configuration"
331 << m_xmlconf << std::endl;
336 void xml_error ( xmlTextReader* reader, std::string msg)
338 std::cerr << "ERROR: " << msg << " "
339 << xmlTextReaderGetParserLineNumber(reader) << ":"
340 << xmlTextReaderGetParserColumnNumber(reader) << " "
341 << xmlTextReaderConstName(reader) << " "
342 << xmlTextReaderDepth(reader) << " "
343 << xmlTextReaderNodeType(reader) << std::endl;
346 void xml_debug_print ( xmlTextReader* reader)
348 // processing all other elements
349 //while (xmlTextReaderMoveToElement(reader)) // reads next element ??
350 //while (xmlTextReaderNext(reader)) //does not descend, keeps level
351 while (xmlTextReaderRead(reader)) // descends into all subtree nodes
352 std::cout << xmlTextReaderGetParserLineNumber(reader) << ":"
353 << xmlTextReaderGetParserColumnNumber(reader) << " "
354 << xmlTextReaderDepth(reader) << " "
355 << xmlTextReaderNodeType(reader) << " "
356 << "ConstName " << xmlTextReaderConstName(reader) << " "
360 bool xml_progress_deep_to_element(xmlTextReader* reader)
363 while(xmlTextReaderRead(reader)
364 && xmlTextReaderNodeType(reader) != XML_ELEMENT_NODE
365 && !( xmlTextReaderNodeType(reader)
366 == XML_READER_TYPE_END_ELEMENT
367 && 0 == xmlTextReaderDepth(reader))
373 bool xml_progress_flat_to_element(xmlTextReader* reader)
377 while(xmlTextReaderNext(reader)
378 && xmlTextReaderNodeType(reader) != XML_ELEMENT_NODE
379 && !( xmlTextReaderNodeType(reader)
380 == XML_READER_TYPE_END_ELEMENT
381 && 0 == xmlTextReaderDepth(reader))
398 * indent-tabs-mode: nil
399 * c-file-style: "stroustrup"
401 * vim: shiftwidth=4 tabstop=8 expandtab