1 // Template for defining an XML parser based on an element type and
4 #ifndef SIMGEAR_XMLSTATICPARSER_HXX
5 #define SIMGEAR_XMLSTATICPARSER_HXX 1
12 #include <osg/ref_ptr>
13 #include <osg/Referenced>
15 #include "easyxml.hxx"
20 template <typename Element> class XMLStaticParser;
22 // Parser object. Instantiated for each new element encountered.
24 template<typename Element>
25 struct ElementBuilder : public osg::Referenced
27 ElementBuilder(XMLStaticParser<Element>* builder) {}
28 ElementBuilder(const ElementBuilder& rhs) const {}
29 virtual ~ElementBuilder() {}
30 virtual void initialize(const XMLAttributes& attributes) = 0;
31 virtual void processSubElement(Element* subElement) = 0;
32 virtual void processData(const char* data, int length) = 0;
33 virtual Element* finalize() = 0;
34 // Create element parser from prototype
35 virtual ElementBuilder* clone() const = 0;
38 template<typename Element>
39 struct BuilderFactory : public osg::Referenced
41 typedef ElementBuilder<Element> builder_type;
42 typedef std::map<std::string, osg::ref_ptr<const ElementBuilder> >
44 BuilderMap builderMap;
45 ~virtual BuilderFactory() {}
46 static void registerBuilder(const std::string& name,
47 const builder_type* prototype)
49 if (!builderFactory.valid())
50 builderFactory = new BuilderFactory;
51 builderFactory->builderMap[name] = prototype;
55 template <typename Element>
56 class XMLStaticParser : public XMLVisitor
61 static osg::ref_ptr<BuilderFactory> builderFactory;
65 static ElementBuilder* makeBuilder(const std::string& name)
67 BuilderMap::iterator iter = builderFactory->builderMap.find(name);
68 if (iter == builderFactory->builderMap.end())
70 return iter->second->clone();
73 typedef std::stack<osg::ref_ptr<ElementBuilder> > BuilderStack;
74 BuilderStack builderStack;
78 XMLStaticParser() : result(0) {}
79 virtual ~XMLStaticParser() {}
81 virtual void startXML()
83 builderStack.push(makeBuilder(""));
88 // Stack should have only the initial builder
89 result = builderStack.top()->finalize();
92 virtual void startElement(const char* name, const XMLAttributes& atts)
94 ElementBuilder* builder = makeBuilder(name);
96 builderStack.push(builder);
97 builder->initialize(atts);
101 virtual void endElement(const char* name)
103 Element* result = builderStack.top()->finalize();
105 if (!builderStack.empty())
106 builderStack.top()->processSubElement(result);
109 virtual void data(const char* s, int length)
111 builderStack.top()->processData(s, length);
114 struct RegisterBuilderProxy
116 RegisterBuilderProxy(const char* name, ElementBuilder* builder)
118 registerBuilder(name, builder);
123 template <typename E>
124 static osg::ref_ptr<BuilderFactory<E> > builderFactory;