1 // easyxml.cxx - implementation of EasyXML interfaces.
3 #include <simgear/compiler.h>
5 #include <string.h> // strcmp()
13 SG_USING_STD(ifstream);
17 ////////////////////////////////////////////////////////////////////////
18 // Implementation of XMLAttributes.
19 ////////////////////////////////////////////////////////////////////////
21 XMLAttributes::XMLAttributes ()
25 XMLAttributes::~XMLAttributes ()
30 XMLAttributes::findAttribute (const char * name) const
33 for (int i = 0; i < s; i++) {
34 if (strcmp(name, getName(i)) == 0)
41 XMLAttributes::hasAttribute (const char * name) const
43 return (findAttribute(name) != -1);
47 XMLAttributes::getValue (const char * name) const
49 int pos = findAttribute(name);
57 ////////////////////////////////////////////////////////////////////////
58 // Implementation of XMLAttributesDefault.
59 ////////////////////////////////////////////////////////////////////////
61 XMLAttributesDefault::XMLAttributesDefault ()
65 XMLAttributesDefault::XMLAttributesDefault (const XMLAttributes &atts)
68 for (int i = 0; i < s; i++)
69 addAttribute(atts.getName(i), atts.getValue(i));
72 XMLAttributesDefault::~XMLAttributesDefault ()
77 XMLAttributesDefault::size () const
79 return _atts.size() / 2;
83 XMLAttributesDefault::getName (int i) const
85 return _atts[i*2].c_str();
89 XMLAttributesDefault::getValue (int i) const
91 return _atts[i*2+1].c_str();
95 XMLAttributesDefault::addAttribute (const char * name, const char * value)
97 _atts.push_back(name);
98 _atts.push_back(value);
102 XMLAttributesDefault::setName (int i, const char * name)
108 XMLAttributesDefault::setValue (int i, const char * name)
114 XMLAttributesDefault::setValue (const char * name, const char * value)
116 int pos = findAttribute(name);
119 setValue(pos, value);
121 addAttribute(name, value);
127 ////////////////////////////////////////////////////////////////////////
128 // Attribute list wrapper for Expat.
129 ////////////////////////////////////////////////////////////////////////
131 class ExpatAtts : public XMLAttributes
134 ExpatAtts (const char ** atts) : _atts(atts) {}
136 virtual int size () const;
137 virtual const char * getName (int i) const;
138 virtual const char * getValue (int i) const;
145 ExpatAtts::size () const
148 for (int i = 0; _atts[i] != 0; i += 2)
154 ExpatAtts::getName (int i) const
160 ExpatAtts::getValue (int i) const
167 ////////////////////////////////////////////////////////////////////////
168 // Static callback functions for Expat.
169 ////////////////////////////////////////////////////////////////////////
171 #define VISITOR (*((XMLVisitor *)userData))
174 start_element (void * userData, const char * name, const char ** atts)
176 VISITOR.startElement(name, ExpatAtts(atts));
180 end_element (void * userData, const char * name)
182 VISITOR.endElement(name);
186 character_data (void * userData, const char * s, int len)
188 VISITOR.data(s, len);
192 processing_instruction (void * userData,
196 VISITOR.pi(target, data);
203 ////////////////////////////////////////////////////////////////////////
204 // Implementation of XMLReader.
205 ////////////////////////////////////////////////////////////////////////
208 readXML (istream &input, XMLVisitor &visitor, const string &path)
210 XML_Parser parser = XML_ParserCreate(0);
211 XML_SetUserData(parser, &visitor);
212 XML_SetElementHandler(parser, start_element, end_element);
213 XML_SetCharacterDataHandler(parser, character_data);
214 XML_SetProcessingInstructionHandler(parser, processing_instruction);
219 while (!input.eof()) {
221 // FIXME: get proper error string from system
223 XML_ParserFree(parser);
224 throw sg_io_exception("Problem reading file",
226 XML_GetCurrentLineNumber(parser),
227 XML_GetCurrentColumnNumber(parser)),
228 "SimGear XML Parser");
231 input.read(buf,16384);
232 if (!XML_Parse(parser, buf, input.gcount(), false)) {
233 XML_ParserFree(parser);
234 throw sg_io_exception(XML_ErrorString(XML_GetErrorCode(parser)),
236 XML_GetCurrentLineNumber(parser),
237 XML_GetCurrentColumnNumber(parser)),
238 "SimGear XML Parser");
243 // Verify end of document.
244 if (!XML_Parse(parser, buf, 0, true)) {
245 XML_ParserFree(parser);
246 throw sg_io_exception(XML_ErrorString(XML_GetErrorCode(parser)),
248 XML_GetCurrentLineNumber(parser),
249 XML_GetCurrentColumnNumber(parser)),
250 "SimGear XML Parser");
253 XML_ParserFree(parser);
257 readXML (const string &path, XMLVisitor &visitor)
259 ifstream input(path.c_str());
262 readXML(input, visitor, path);
263 } catch (sg_io_exception &e) {
266 } catch (sg_throwable &t) {
271 throw sg_io_exception("Failed to open file", sg_location(path),
272 "SimGear XML Parser");
278 readXML (const char *buf, const int size, XMLVisitor &visitor)
280 XML_Parser parser = XML_ParserCreate(0);
281 XML_SetUserData(parser, &visitor);
282 XML_SetElementHandler(parser, start_element, end_element);
283 XML_SetCharacterDataHandler(parser, character_data);
284 XML_SetProcessingInstructionHandler(parser, processing_instruction);
288 if (!XML_Parse(parser, buf, size, false)) {
289 XML_ParserFree(parser);
290 throw sg_io_exception(XML_ErrorString(XML_GetErrorCode(parser)),
291 sg_location("In-memory XML buffer",
292 XML_GetCurrentLineNumber(parser),
293 XML_GetCurrentColumnNumber(parser)),
294 "SimGear XML Parser");
297 XML_ParserFree(parser);
300 // end of easyxml.cxx