Line data Source code
1 : /*************************************************************************
2 : *
3 : * Copyright (c) 2010-2012 Kohei Yoshida
4 : *
5 : * Permission is hereby granted, free of charge, to any person
6 : * obtaining a copy of this software and associated documentation
7 : * files (the "Software"), to deal in the Software without
8 : * restriction, including without limitation the rights to use,
9 : * copy, modify, merge, publish, distribute, sublicense, and/or sell
10 : * copies of the Software, and to permit persons to whom the
11 : * Software is furnished to do so, subject to the following
12 : * conditions:
13 : *
14 : * The above copyright notice and this permission notice shall be
15 : * included in all copies or substantial portions of the Software.
16 : *
17 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 : * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 : * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 : * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 : * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 : * OTHER DEALINGS IN THE SOFTWARE.
25 : *
26 : ************************************************************************/
27 :
28 : #ifndef __ORCUS_SAX_TOKEN_PARSER_HPP__
29 : #define __ORCUS_SAX_TOKEN_PARSER_HPP__
30 :
31 : #include <vector>
32 : #include <algorithm>
33 : #include <functional>
34 :
35 : #include "types.hpp"
36 : #include "sax_parser.hpp"
37 :
38 : namespace orcus {
39 :
40 : namespace sax {
41 :
42 : #if ORCUS_DEBUG_SAX_PARSER
43 : template<typename _Attr, typename _Tokens>
44 : class attr_printer : public ::std::unary_function<_Attr, void>
45 : {
46 : public:
47 : attr_printer(const _Tokens& tokens, const ::std::string& indent) :
48 : m_tokens(tokens), m_indent(indent) {}
49 :
50 : void operator() (const _Attr& attr) const
51 : {
52 : using namespace std;
53 : cout << m_indent << " attribute: "
54 : << m_tokens.get_nstoken_name(attr.ns) << ":"
55 : << m_tokens.get_token_name(attr.name) << "=\""
56 : << attr.value.str() << "\"" << endl;
57 : }
58 : private:
59 : const _Tokens& m_tokens;
60 : ::std::string m_indent;
61 : };
62 : #endif
63 :
64 : }
65 :
66 : /**
67 : * Element properties passed to its handler via start_element() and
68 : * end_element() calls.
69 : */
70 0 : struct sax_token_parser_element
71 : {
72 : xmlns_token_t ns;
73 : xml_token_t name;
74 : std::vector<xml_token_attr_t> attrs;
75 : };
76 :
77 : /**
78 : * XML parser that tokenizes element and attribute names while parsing.
79 : */
80 : template<typename _Handler, typename _Tokens>
81 : class sax_token_parser
82 : {
83 : public:
84 : typedef _Handler handler_type;
85 : typedef _Tokens tokens_map;
86 :
87 : sax_token_parser(const char* content, const size_t size, const tokens_map& tokens, handler_type& handler);
88 : ~sax_token_parser();
89 :
90 : void parse();
91 :
92 : private:
93 :
94 : /**
95 : * Re-route callbacks from the internal sax_parser into the token_parser
96 : * callbacks.
97 : */
98 0 : class handler_wrapper
99 : {
100 : sax_token_parser_element m_elem;
101 : const tokens_map& m_tokens;
102 : handler_type& m_handler;
103 :
104 : public:
105 0 : handler_wrapper(const tokens_map& tokens, handler_type& handler) :
106 0 : m_tokens(tokens), m_handler(handler) {}
107 :
108 : void declaration()
109 : {
110 : m_elem.attrs.clear();
111 : }
112 :
113 0 : void start_element(const sax_parser_element& elem)
114 : {
115 0 : m_elem.ns = tokenize_ns(elem.ns);
116 0 : m_elem.name = tokenize(elem.name);
117 0 : m_handler.start_element(m_elem);
118 : m_elem.attrs.clear();
119 0 : }
120 :
121 0 : void end_element(const sax_parser_element& elem)
122 : {
123 0 : m_elem.ns = tokenize_ns(elem.ns);
124 0 : m_elem.name = tokenize(elem.name);
125 0 : m_handler.end_element(m_elem);
126 0 : }
127 :
128 0 : void characters(const pstring& val)
129 : {
130 0 : m_handler.characters(val);
131 0 : }
132 :
133 0 : void attribute(const pstring& ns, const pstring& name, const pstring& val)
134 : {
135 0 : xml_token_t elem_token = tokenize(name);
136 0 : xmlns_token_t elem_nstoken = tokenize_ns(ns);
137 0 : m_elem.attrs.push_back(xml_token_attr_t(elem_nstoken, elem_token, val));
138 0 : }
139 :
140 : private:
141 0 : xmlns_token_t tokenize_ns(const pstring& ns) const
142 : {
143 : xmlns_token_t token = XMLNS_UNKNOWN_TOKEN;
144 0 : if (!ns.empty())
145 0 : token = m_tokens.get_nstoken(ns);
146 0 : return token;
147 : }
148 :
149 0 : xml_token_t tokenize(const pstring& name) const
150 : {
151 : xml_token_t token = XML_UNKNOWN_TOKEN;
152 0 : if (!name.empty())
153 0 : token = m_tokens.get_token(name);
154 0 : return token;
155 : }
156 : };
157 :
158 : private:
159 : handler_wrapper m_wrapper;
160 : sax_parser<handler_wrapper> m_parser;
161 : };
162 :
163 : template<typename _Handler, typename _Tokens>
164 0 : sax_token_parser<_Handler,_Tokens>::sax_token_parser(
165 : const char* content, const size_t size, const tokens_map& tokens, handler_type& handler) :
166 : m_wrapper(tokens, handler),
167 0 : m_parser(content, size, m_wrapper)
168 : {
169 0 : }
170 :
171 : template<typename _Handler, typename _Tokens>
172 0 : sax_token_parser<_Handler,_Tokens>::~sax_token_parser()
173 : {
174 0 : }
175 :
176 : template<typename _Handler, typename _Tokens>
177 0 : void sax_token_parser<_Handler,_Tokens>::parse()
178 : {
179 0 : m_parser.parse();
180 0 : }
181 :
182 : }
183 :
184 : #endif
|