1 // 2 // Copyright (C) 2009, 2012 Nick Gasson 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 // 17 18 #ifndef INC_IXMLPARSER_HPP 19 #define INC_IXMLPARSER_HPP 20 21 #include "Platform.hpp" 22 #include "Colour.hpp" 23 24 #include <string> 25 #include <stdexcept> 26 #include <sstream> 27 28 #include <boost/lexical_cast.hpp> 29 30 #include <xercesc/sax2/Attributes.hpp> 31 #include <xercesc/util/XMLString.hpp> 32 33 // Container for attributes 34 class AttributeSet { 35 public: AttributeSet(const xercesc::Attributes & attrs)36 AttributeSet(const xercesc::Attributes& attrs) 37 : my_attrs(attrs) {} 38 has(const string & name) const39 bool has(const string& name) const 40 { 41 XMLCh* xml_name = xercesc::XMLString::transcode(name.c_str()); 42 43 int index = my_attrs.getIndex(xml_name); 44 xercesc::XMLString::release(&xml_name); 45 46 return index != -1; 47 } 48 49 template <class T> get(const string & a_name) const50 T get(const string& a_name) const 51 { 52 XMLCh* xml_name = xercesc::XMLString::transcode(a_name.c_str()); 53 54 int index = my_attrs.getIndex(xml_name); 55 xercesc::XMLString::release(&xml_name); 56 57 if (index != -1) { 58 char* ascii = xercesc::XMLString::transcode( 59 my_attrs.getValue(index)); 60 61 T result = xml_attr_cast<T>(ascii); 62 63 xercesc::XMLString::release(&ascii); 64 return result; 65 } 66 else 67 throw std::runtime_error("No attribute: " + a_name); 68 } 69 70 template <class T> get(const string & a_name,T & aT) const71 void get(const string& a_name, T& aT) const 72 { 73 aT = get<T>(a_name); 74 } 75 76 // Get with default 77 template <class T> get(const string & name,const T & def) const78 T get(const string& name, const T& def) const 79 { 80 return has(name) ? get<T>(name) : def; 81 } 82 83 private: 84 const xercesc::Attributes& my_attrs; 85 86 template <class T> xml_attr_cast(const string & str)87 static T xml_attr_cast(const string& str) 88 { 89 return boost::lexical_cast<T>(str); 90 } 91 92 }; 93 94 template <> 95 bool AttributeSet::xml_attr_cast(const string& str); 96 97 template <> 98 Colour AttributeSet::xml_attr_cast(const string& str); 99 100 101 // SAX-like interface to XML parsing 102 struct IXMLCallback { ~IXMLCallbackIXMLCallback103 virtual ~IXMLCallback() {} 104 start_elementIXMLCallback105 virtual void start_element(const string& local_name, 106 const AttributeSet& attrs) {} end_elementIXMLCallback107 virtual void end_element(const string& local_name) {} textIXMLCallback108 virtual void text(const string& local_name, 109 const string& a_string) {} 110 }; 111 112 // Interface to a validating XML parser 113 struct IXMLParser { ~IXMLParserIXMLParser114 virtual ~IXMLParser() {} 115 116 virtual void parse(const string& a_file_name, 117 IXMLCallback& a_callback) = 0; 118 }; 119 120 typedef shared_ptr<IXMLParser> IXMLParserPtr; 121 122 IXMLParserPtr make_xml_parser(const std::string& a_schema_file); 123 124 #endif 125