1 #include <libxml++/libxml++.h>
5 void print_indentation(unsigned int indentation)
7 for(unsigned int i = 0; i < indentation; ++i)
13 //! get child element by id
15 \return pointer to element having id or null on error
16 \todo find libxmlpp pendant
18 const xmlpp::Element* get_element_by_id(const xmlpp::Element* element, const std::string &id)
20 const xmlpp::Attribute* cid = element->get_attribute("id");
21 if ( cid && ( cid->get_value() == id)) return element;
23 //Recurse through child nodes:
24 xmlpp::Node::NodeList list = element->get_children();
25 for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
27 const xmlpp::Element* element = dynamic_cast<const xmlpp::Element*>(*iter);
29 const xmlpp::Element* match = get_element_by_id(element, id);
30 if (match) return match;
36 //! get namespace by id
38 \return namespace name or empty string on error
40 std::string get_namespace(const xmlpp::Element* root, const std::string &id)
43 const xmlpp::Element* element(get_element_by_id(root, id));
44 if ((!element)||(!element->get_attribute("name"))) return error;
45 return element->get_attribute("name")->get_value();
50 \return type name or empty string on error
52 std::string get_type(const xmlpp::Element* root, const std::string &id)
55 const xmlpp::Element* element(get_element_by_id(root, id));
56 if (!element) return error;
58 // TODO: not yet complete
59 // if we recurse - when do we stop?
60 // if it is a typedef? yes? (hmm if the typedef is in the file parsed this will not work)
61 std::string tag(element->get_name());
62 if (tag=="ReferenceType") {
63 assert(element->get_attribute("type"));
64 std::string ret(get_type(root, element->get_attribute("type")->get_value()));
65 if (ret==error) return error;
67 }else if (tag=="CvQualifiedType") {
68 assert(element->get_attribute("type"));
69 std::string ret(get_type(root, element->get_attribute("type")->get_value()));
70 if (ret==error) return error;
71 return std::string("const ")+ret;
74 assert(element->get_attribute("name"));
75 assert(element->get_attribute("context"));
76 return get_namespace(root, element->get_attribute("context")->get_value())+"::"+element->get_attribute("name")->get_value();
79 void parse_function(const xmlpp::Element* root, const xmlpp::Node* node, unsigned int indentation = 0) {
80 const xmlpp::Element* element = dynamic_cast<const xmlpp::Element*>(node);
83 const xmlpp::Attribute* attributes = element->get_attribute("attributes");
84 const xmlpp::Attribute* name = element->get_attribute("name");
85 const xmlpp::Attribute* returns = element->get_attribute("returns");
86 if ((!attributes)||(!name)||(!returns)) return;
88 // check wether the function is marked (TODO: improve)
89 if (attributes->get_value().find("gccxml(libt2n")==std::string::npos) return;
91 // TODO: extract command group
92 // something like: sed 's,gccxml(libt2n-\([a-z]*}),\1,'
94 // we need the return type
95 std::string ret_type(get_type(root, returns->get_value()));
97 // and the argument types
98 typedef std::map<std::string, std::string> Args;
101 xmlpp::Node::NodeList list = node->get_children("Argument");
102 for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
104 const xmlpp::Element* arg = dynamic_cast<const xmlpp::Element*>(*iter);
106 assert(arg->get_name() == "Argument");
107 assert(arg->get_attribute("name"));
108 assert(arg->get_attribute("type"));
109 assert(args.find(arg->get_attribute("name")->get_value())==args.end());
110 args[arg->get_attribute("name")->get_value()]=get_type(root, arg->get_attribute("type")->get_value());
114 std::cerr << "Found marked Function: " << ret_type << " " << name->get_value() << "(";
115 for (Args::const_iterator it=args.begin();it!=args.end();++it) {
116 if (it!=args.begin()) std::cerr << ", ";
117 std::cerr << it->second << " " << it->first;
119 std::cerr << ");" << std::endl;
122 void print_node(const xmlpp::Element* root, const xmlpp::Node* node = NULL, unsigned int indentation = 0)
124 if (!node) node=root;
125 std::cout << std::endl; //Separate nodes by an empty line.
127 const xmlpp::ContentNode* nodeContent = dynamic_cast<const xmlpp::ContentNode*>(node);
128 const xmlpp::TextNode* nodeText = dynamic_cast<const xmlpp::TextNode*>(node);
129 const xmlpp::CommentNode* nodeComment = dynamic_cast<const xmlpp::CommentNode*>(node);
131 if(nodeText && nodeText->is_white_space()) //Let's ignore the indenting - you don't always want to do this.
134 std::string nodename = node->get_name();
136 if(!nodeText && !nodeComment && !nodename.empty()) //Let's not say "name: text".
138 print_indentation(indentation);
139 // std::cout << "Node name = " << node->get_name() << std::endl;
140 // std::cout << "Node name = " << nodename << std::endl;
141 if (node->get_name() == "Function") {
142 parse_function(root, node, indentation);
145 else if(nodeText) //Let's say when it's text. - e.g. let's say what that white space is.
147 print_indentation(indentation);
148 std::cout << "Text Node" << std::endl;
151 //Treat the various node types differently:
154 print_indentation(indentation);
155 std::cout << "text = \"" << nodeText->get_content() << "\"" << std::endl;
159 print_indentation(indentation);
160 std::cout << "comment = " << nodeComment->get_content() << std::endl;
164 print_indentation(indentation);
165 std::cout << "content = " << nodeContent->get_content() << std::endl;
167 else if(const xmlpp::Element* nodeElement = dynamic_cast<const xmlpp::Element*>(node))
169 //A normal Element node:
171 //line() works only for ElementNodes.
172 print_indentation(indentation);
173 std::cout << " line = " << node->get_line() << std::endl;
176 const xmlpp::Element::AttributeList& attributes = nodeElement->get_attributes();
177 for(xmlpp::Element::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
179 const xmlpp::Attribute* attribute = *iter;
180 print_indentation(indentation);
181 std::cout << " Attribute " << attribute->get_name() << " = " << attribute->get_value() << std::endl;
184 const xmlpp::Attribute* attribute = nodeElement->get_attribute("title");
187 std::cout << "title found: =" << attribute->get_value() << std::endl;
194 //Recurse through child nodes:
195 xmlpp::Node::NodeList list = node->get_children();
196 for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
198 print_node(root, *iter, indentation + 2); //recursive
203 int main(int argc, char* argv[])
205 std::string filepath;
207 filepath = argv[1]; //Allow the user to specify a different XML file to parse.
209 filepath = "example.xml";
213 xmlpp::DomParser parser;
214 // parser.set_validate();
215 parser.set_substitute_entities(); //We just want the text to be resolved/unescaped automatically.
216 parser.parse_file(filepath);
220 const xmlpp::Node* pNode = parser.get_document()->get_root_node(); //deleted by DomParser.
221 const xmlpp::Element* root = dynamic_cast<const xmlpp::Element*>(pNode);
226 catch(const std::exception& ex)
228 std::cout << "Exception caught: " << ex.what() << std::endl;