Windows: use Boost 1.59, msvc 14.0
[metaproxy-moved-to-github.git] / src / xmlutil.cpp
1 /* This file is part of Metaproxy.
2    Copyright (C) Index Data
3
4 Metaproxy is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19 #include "config.hpp"
20
21 #include <metaproxy/xmlutil.hpp>
22
23 #include <string.h>
24
25 namespace mp = metaproxy_1;
26 // Doxygen doesn't like mp::xml, so we use this instead
27 namespace mp_xml = metaproxy_1::xml;
28
29 static const std::string metaproxy_ns = "http://indexdata.com/metaproxy";
30
31 std::string mp_xml::get_text(const struct _xmlAttr  *ptr)
32 {
33     return get_text(ptr->children);
34 }
35
36 std::string mp_xml::get_text(const xmlNode *ptr)
37 {
38     std::string c;
39     if (ptr && ptr->type != XML_TEXT_NODE)
40         ptr = ptr->children;
41     for (; ptr; ptr = ptr->next)
42         if (ptr->type == XML_TEXT_NODE)
43             c += std::string((const char *) (ptr->content));
44     return c;
45 }
46
47 bool mp_xml::get_bool(const xmlNode *ptr, bool default_value)
48 {
49     if (ptr && ptr->type != XML_TEXT_NODE)
50         ptr = ptr->children;
51     if (ptr && ptr->type == XML_TEXT_NODE && ptr->content)
52     {
53         if (!strcmp((const char *) ptr->content, "true")
54             || !strcmp((const char *) ptr->content, "1"))
55             return true;
56         else
57             return false;
58     }
59     return default_value;
60 }
61
62 int mp_xml::get_int(const xmlNode *ptr, int default_value)
63 {
64     if (ptr && ptr->type != XML_TEXT_NODE)
65         ptr = ptr->children;
66     if (ptr && ptr->type == XML_TEXT_NODE && ptr->content)
67     {
68         return atoi((const char *) ptr->content);
69     }
70     return default_value;
71 }
72
73 bool mp_xml::check_attribute(const _xmlAttr *ptr,
74                              const std::string &ns,
75                              const std::string &name)
76 {
77     if (!mp::xml::is_attribute(ptr, ns, name))
78     {
79         std::string got_attr = "'";
80         if (ptr && ptr->name)
81             got_attr += std::string((const char *)ptr->name);
82         if (ns.size() && ptr && ptr->ns && ptr->ns->href){
83             got_attr += " ";
84             got_attr += std::string((const char *)ptr->ns->href);
85          }
86         got_attr += "'";
87
88         throw mp::XMLError("Expected XML attribute '" + name
89                            + " " + ns + "'"
90                            + ", not " + got_attr);
91     }
92     return true;
93 }
94
95 bool mp_xml::is_attribute(const _xmlAttr *ptr,
96                           const std::string &ns,
97                           const std::string &name)
98 {
99     if (0 != xmlStrcmp(BAD_CAST name.c_str(), ptr->name))
100         return false;
101
102     if (ns.size()
103         && (!ptr->ns || !ptr->ns->href
104             || 0 != xmlStrcmp(BAD_CAST ns.c_str(), ptr->ns->href)))
105         return false;
106
107     return true;
108 }
109
110
111 bool mp_xml::is_element(const xmlNode *ptr,
112                           const std::string &ns,
113                           const std::string &name)
114 {
115     if (ptr && ptr->type == XML_ELEMENT_NODE && ptr->ns && ptr->ns->href
116         && !xmlStrcmp(BAD_CAST ns.c_str(), ptr->ns->href)
117         && !xmlStrcmp(BAD_CAST name.c_str(), ptr->name))
118         return true;
119     return false;
120 }
121
122 bool mp_xml::is_element_mp(const xmlNode *ptr,
123                            const std::string &name)
124 {
125     return mp::xml::is_element(ptr, metaproxy_ns, name);
126 }
127
128
129 bool mp_xml::check_element_mp(const xmlNode *ptr,
130                               const std::string &name)
131 {
132     if (!mp::xml::is_element_mp(ptr, name))
133     {
134         std::string got_element = "<";
135         if (ptr && ptr->name)
136             got_element += std::string((const char *)ptr->name);
137         if (ptr && ptr->ns && ptr->ns->href){
138             got_element += " xmlns=\"";
139             got_element += std::string((const char *)ptr->ns->href);
140             got_element += "\"";
141         }
142         got_element += ">";
143
144         throw mp::XMLError("Expected XML element <" + name
145                            + " xmlns=\"" + metaproxy_ns + "\">"
146                            + ", not " + got_element);
147     }
148     return true;
149 }
150
151 void mp_xml::parse_attr(const xmlNode *node, const char **names,
152                         std::string *values)
153 {
154     size_t i;
155     for (i = 0; names[i]; i++)
156         values[i].clear();
157
158     if (node)
159     {
160         const struct _xmlAttr *attr;
161         for (attr = node->properties; attr; attr = attr->next)
162         {
163             std::string value;
164             const char *name = (const char *) attr->name;
165
166             if (attr->children && attr->children->type == XML_TEXT_NODE)
167                 value = std::string((const char *)attr->children->content);
168             for (i = 0; names[i]; i++)
169                 if (!strcmp(name, names[i]))
170                 {
171                     values[i] = value;
172                     break;
173                 }
174             if (!names[i])
175             {
176                 throw XMLError("Unsupported attribute: '" +
177                                std::string(name) +
178                                "' in element '" + 
179                                std::string((const char *) node->name) + "'");
180             }
181         }
182     }
183 }
184
185 std::string mp_xml::get_route(const xmlNode *node, std::string &auth)
186 {
187     const char *names[3] = { "route", "auth", 0 };
188     std::string values[2];
189
190     parse_attr(node, names, values);
191
192     auth = values[1];
193     return values[0];
194 }
195
196 std::string mp_xml::get_route(const xmlNode *node)
197 {
198     const char *names[2] = { "route", 0 };
199     std::string values[1];
200
201     parse_attr(node, names, values);
202
203     return values[0];
204 }
205
206 const xmlNode* mp_xml::jump_to_children(const xmlNode* node,
207                                           int xml_node_type)
208 {
209     node = node->children;
210     for (; node && node->type != xml_node_type; node = node->next)
211         ;
212     return node;
213 }
214
215 const xmlNode* mp_xml::jump_to_next(const xmlNode* node,
216                                       int xml_node_type)
217 {
218     node = node->next;
219     for (; node && node->type != xml_node_type; node = node->next)
220         ;
221     return node;
222 }
223
224 const xmlNode* mp_xml::jump_to(const xmlNode* node,
225                                  int xml_node_type)
226 {
227     for (; node && node->type != xml_node_type; node = node->next)
228         ;
229     return node;
230 }
231
232 void mp_xml::check_empty(const xmlNode *node)
233 {
234     if (node)
235     {
236         const xmlNode *n;
237         const struct _xmlAttr *attr;
238         std::string extra;
239         for (attr = node->properties; attr; attr = attr->next)
240             if (!strcmp((const char *) attr->name, "type"))
241                 extra = " of type " + get_text(attr);
242         for (n = node->children; n; n = n->next)
243             if (n->type == XML_ELEMENT_NODE)
244                 throw mp::XMLError("No child elements allowed inside element "
245                                    + std::string((const char *) node->name)
246                                    + extra);
247     }
248 }
249
250 /*
251  * Local variables:
252  * c-basic-offset: 4
253  * c-file-style: "Stroustrup"
254  * indent-tabs-mode: nil
255  * End:
256  * vim: shiftwidth=4 tabstop=8 expandtab
257  */
258