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