2 * \file easyxml.cxx - implementation of EasyXML interfaces.
3 * Written by David Megginson, 2000-2001
4 * This file is in the Public Domain, and comes with NO WARRANTY of any kind.
7 #include <simgear/compiler.h>
9 #include <string.h> // strcmp()
11 #include "easyxml.hxx"
21 ////////////////////////////////////////////////////////////////////////
22 // Implementation of XMLAttributes.
23 ////////////////////////////////////////////////////////////////////////
25 XMLAttributes::XMLAttributes ()
29 XMLAttributes::~XMLAttributes ()
34 XMLAttributes::findAttribute (const char * name) const
37 for (int i = 0; i < s; i++) {
38 if (strcmp(name, getName(i)) == 0)
45 XMLAttributes::hasAttribute (const char * name) const
47 return (findAttribute(name) != -1);
51 XMLAttributes::getValue (const char * name) const
53 int pos = findAttribute(name);
61 ////////////////////////////////////////////////////////////////////////
62 // Implementation of XMLAttributesDefault.
63 ////////////////////////////////////////////////////////////////////////
65 XMLAttributesDefault::XMLAttributesDefault ()
69 XMLAttributesDefault::XMLAttributesDefault (const XMLAttributes &atts)
72 for (int i = 0; i < s; i++)
73 addAttribute(atts.getName(i), atts.getValue(i));
76 XMLAttributesDefault::~XMLAttributesDefault ()
81 XMLAttributesDefault::size () const
83 return _atts.size() / 2;
87 XMLAttributesDefault::getName (int i) const
89 return _atts[i*2].c_str();
93 XMLAttributesDefault::getValue (int i) const
95 return _atts[i*2+1].c_str();
99 XMLAttributesDefault::addAttribute (const char * name, const char * value)
101 _atts.push_back(name);
102 _atts.push_back(value);
106 XMLAttributesDefault::setName (int i, const char * name)
112 XMLAttributesDefault::setValue (int i, const char * name)
118 XMLAttributesDefault::setValue (const char * name, const char * value)
120 int pos = findAttribute(name);
123 setValue(pos, value);
125 addAttribute(name, value);
131 ////////////////////////////////////////////////////////////////////////
132 // Attribute list wrapper for Expat.
133 ////////////////////////////////////////////////////////////////////////
135 class ExpatAtts : public XMLAttributes
138 ExpatAtts (const char ** atts) : _atts(atts) {}
140 virtual int size () const;
141 virtual const char * getName (int i) const;
142 virtual const char * getValue (int i) const;
149 ExpatAtts::size () const
152 for (int i = 0; _atts[i] != 0; i += 2)
158 ExpatAtts::getName (int i) const
164 ExpatAtts::getValue (int i) const
171 ////////////////////////////////////////////////////////////////////////
172 // Static callback functions for Expat.
173 ////////////////////////////////////////////////////////////////////////
175 #define VISITOR (*((XMLVisitor *)userData))
178 start_element (void * userData, const char * name, const char ** atts)
180 VISITOR.startElement(name, ExpatAtts(atts));
184 end_element (void * userData, const char * name)
186 VISITOR.endElement(name);
190 character_data (void * userData, const char * s, int len)
192 VISITOR.data(s, len);
196 processing_instruction (void * userData,
200 VISITOR.pi(target, data);
207 ////////////////////////////////////////////////////////////////////////
208 // Implementation of XMLReader.
209 ////////////////////////////////////////////////////////////////////////
212 readXML (istream &input, XMLVisitor &visitor, const string &path)
214 XML_Parser parser = XML_ParserCreate(0);
215 XML_SetUserData(parser, &visitor);
216 XML_SetElementHandler(parser, start_element, end_element);
217 XML_SetCharacterDataHandler(parser, character_data);
218 XML_SetProcessingInstructionHandler(parser, processing_instruction);
223 while (!input.eof()) {
225 // FIXME: get proper error string from system
227 sg_io_exception ex ("Problem reading file",
229 XML_GetCurrentLineNumber(parser),
230 XML_GetCurrentColumnNumber(parser)),
231 "SimGear XML Parser");
232 XML_ParserFree(parser);
236 input.read(buf,16384);
237 if (!XML_Parse(parser, buf, input.gcount(), false)) {
238 sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)),
240 XML_GetCurrentLineNumber(parser),
241 XML_GetCurrentColumnNumber(parser)),
242 "SimGear XML Parser");
243 XML_ParserFree(parser);
249 // Verify end of document.
250 if (!XML_Parse(parser, buf, 0, true)) {
251 sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)),
253 XML_GetCurrentLineNumber(parser),
254 XML_GetCurrentColumnNumber(parser)),
255 "SimGear XML Parser");
256 XML_ParserFree(parser);
260 XML_ParserFree(parser);
265 readXML (const string &path, XMLVisitor &visitor)
267 ifstream input(path.c_str());
270 readXML(input, visitor, path);
271 } catch (sg_io_exception &) {
274 } catch (sg_throwable &) {
279 throw sg_io_exception("Failed to open file", sg_location(path),
280 "SimGear XML Parser");
286 readXML (const char *buf, const int size, XMLVisitor &visitor)
288 XML_Parser parser = XML_ParserCreate(0);
289 XML_SetUserData(parser, &visitor);
290 XML_SetElementHandler(parser, start_element, end_element);
291 XML_SetCharacterDataHandler(parser, character_data);
292 XML_SetProcessingInstructionHandler(parser, processing_instruction);
296 if (!XML_Parse(parser, buf, size, false)) {
297 sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)),
298 sg_location("In-memory XML buffer",
299 XML_GetCurrentLineNumber(parser),
300 XML_GetCurrentColumnNumber(parser)),
301 "SimGear XML Parser");
302 XML_ParserFree(parser);
306 XML_ParserFree(parser);
310 // end of easyxml.cxx