1 // easyxml.cxx - implementation of EasyXML interfaces.
3 #include <simgear/compiler.h>
5 #include <string.h> // strcmp()
12 SG_USING_STD(ifstream);
16 ////////////////////////////////////////////////////////////////////////
17 // Implementation of sg_xml_exception.
18 ////////////////////////////////////////////////////////////////////////
20 sg_xml_exception::sg_xml_exception ()
21 : sg_io_exception("", "SimGear XML parser")
25 sg_xml_exception::sg_xml_exception (const string &message)
26 : sg_io_exception(message, "SimGear XML parser")
30 sg_xml_exception::sg_xml_exception (const string &message,
31 const sg_location &location)
32 : sg_io_exception(message, location, "SimGear XML parser")
36 sg_xml_exception::~sg_xml_exception ()
42 ////////////////////////////////////////////////////////////////////////
43 // Implementation of XMLAttributes.
44 ////////////////////////////////////////////////////////////////////////
46 XMLAttributes::XMLAttributes ()
50 XMLAttributes::~XMLAttributes ()
55 XMLAttributes::findAttribute (const char * name) const
58 for (int i = 0; i < s; i++) {
59 if (strcmp(name, getName(i)) == 0)
66 XMLAttributes::hasAttribute (const char * name) const
68 return (findAttribute(name) != -1);
72 XMLAttributes::getValue (const char * name) const
74 int pos = findAttribute(name);
82 ////////////////////////////////////////////////////////////////////////
83 // Implementation of XMLAttributesDefault.
84 ////////////////////////////////////////////////////////////////////////
86 XMLAttributesDefault::XMLAttributesDefault ()
90 XMLAttributesDefault::XMLAttributesDefault (const XMLAttributes &atts)
93 for (int i = 0; i < s; i++)
94 addAttribute(atts.getName(i), atts.getValue(i));
97 XMLAttributesDefault::~XMLAttributesDefault ()
102 XMLAttributesDefault::size () const
104 return _atts.size() / 2;
108 XMLAttributesDefault::getName (int i) const
110 return _atts[i*2].c_str();
114 XMLAttributesDefault::getValue (int i) const
116 return _atts[i*2+1].c_str();
120 XMLAttributesDefault::addAttribute (const char * name, const char * value)
122 _atts.push_back(name);
123 _atts.push_back(value);
127 XMLAttributesDefault::setName (int i, const char * name)
133 XMLAttributesDefault::setValue (int i, const char * name)
139 XMLAttributesDefault::setValue (const char * name, const char * value)
141 int pos = findAttribute(name);
144 setValue(pos, value);
146 addAttribute(name, value);
152 ////////////////////////////////////////////////////////////////////////
153 // Attribute list wrapper for Expat.
154 ////////////////////////////////////////////////////////////////////////
156 class ExpatAtts : public XMLAttributes
159 ExpatAtts (const char ** atts) : _atts(atts) {}
161 virtual int size () const;
162 virtual const char * getName (int i) const;
163 virtual const char * getValue (int i) const;
170 ExpatAtts::size () const
173 for (int i = 0; _atts[i] != 0; i += 2)
179 ExpatAtts::getName (int i) const
185 ExpatAtts::getValue (int i) const
192 ////////////////////////////////////////////////////////////////////////
193 // Static callback functions for Expat.
194 ////////////////////////////////////////////////////////////////////////
196 #define VISITOR (*((XMLVisitor *)userData))
199 start_element (void * userData, const char * name, const char ** atts)
201 VISITOR.startElement(name, ExpatAtts(atts));
205 end_element (void * userData, const char * name)
207 VISITOR.endElement(name);
211 character_data (void * userData, const char * s, int len)
213 VISITOR.data(s, len);
217 processing_instruction (void * userData,
221 VISITOR.pi(target, data);
228 ////////////////////////////////////////////////////////////////////////
229 // Implementation of XMLReader.
230 ////////////////////////////////////////////////////////////////////////
233 readXML (istream &input, XMLVisitor &visitor, const string &path)
235 XML_Parser parser = XML_ParserCreate(0);
236 XML_SetUserData(parser, &visitor);
237 XML_SetElementHandler(parser, start_element, end_element);
238 XML_SetCharacterDataHandler(parser, character_data);
239 XML_SetProcessingInstructionHandler(parser, processing_instruction);
244 while (!input.eof()) {
246 // FIXME: get proper error string from system
248 XML_ParserFree(parser);
249 throw sg_io_exception("Problem reading file",
251 XML_GetCurrentLineNumber(parser),
252 XML_GetCurrentColumnNumber(parser)));
255 input.read(buf,16384);
256 if (!XML_Parse(parser, buf, input.gcount(), false)) {
257 XML_ParserFree(parser);
258 throw sg_xml_exception(XML_ErrorString(XML_GetErrorCode(parser)),
260 XML_GetCurrentLineNumber(parser),
261 XML_GetCurrentColumnNumber(parser)));
266 // Verify end of document.
267 if (!XML_Parse(parser, buf, 0, true)) {
268 XML_ParserFree(parser);
269 throw sg_xml_exception(XML_ErrorString(XML_GetErrorCode(parser)),
271 XML_GetCurrentLineNumber(parser),
272 XML_GetCurrentColumnNumber(parser)));
275 XML_ParserFree(parser);
279 readXML (const string &path, XMLVisitor &visitor)
281 ifstream input(path.c_str());
283 readXML(input, visitor, path);
285 throw sg_io_exception("Failed to open file", sg_location(path));
289 // end of easyxml.cxx