Happy new year
[metaproxy-moved-to-github.git] / src / xmlutil.cpp
1 /* This file is part of Metaproxy.
2    Copyright (C) 2005-2012 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
78     if (!mp::xml::is_attribute(ptr, ns, name))
79     {   
80         std::string got_attr = "'";
81         if (ptr && ptr->name)
82             got_attr += std::string((const char *)ptr->name);
83         if (ns.size() && ptr && ptr->ns && ptr->ns->href){
84             got_attr += " ";
85             got_attr += std::string((const char *)ptr->ns->href);
86          }
87         got_attr += "'";
88         
89         throw mp::XMLError("Expected XML attribute '" + name 
90                            + " " + ns + "'"
91                            + ", not " + got_attr);
92     }
93     return true;
94 }
95
96 bool mp_xml::is_attribute(const _xmlAttr *ptr, 
97                           const std::string &ns,
98                           const std::string &name)
99 {
100     if (0 != xmlStrcmp(BAD_CAST name.c_str(), ptr->name))
101         return false;
102
103     if (ns.size() 
104         && (!ptr->ns || !ptr->ns->href 
105             || 0 != xmlStrcmp(BAD_CAST ns.c_str(), ptr->ns->href)))
106         return false;
107
108     return true;
109 }
110
111
112 bool mp_xml::is_element(const xmlNode *ptr, 
113                           const std::string &ns,
114                           const std::string &name)
115 {
116     if (ptr && ptr->type == XML_ELEMENT_NODE && ptr->ns && ptr->ns->href 
117         && !xmlStrcmp(BAD_CAST ns.c_str(), ptr->ns->href)
118         && !xmlStrcmp(BAD_CAST name.c_str(), ptr->name))
119         return true;
120     return false;
121 }
122
123 bool mp_xml::is_element_mp(const xmlNode *ptr, 
124                            const std::string &name)
125 {
126     return mp::xml::is_element(ptr, metaproxy_ns, name);
127 }
128
129
130 bool mp_xml::check_element_mp(const xmlNode *ptr, 
131                               const std::string &name)
132 {
133     if (!mp::xml::is_element_mp(ptr, name))
134     {
135         std::string got_element = "<";
136         if (ptr && ptr->name)
137             got_element += std::string((const char *)ptr->name);
138         if (ptr && ptr->ns && ptr->ns->href){
139             got_element += " xmlns=\"";
140             got_element += std::string((const char *)ptr->ns->href);
141             got_element += "\"";
142         }
143         got_element += ">";
144
145         throw mp::XMLError("Expected XML element <" + name 
146                            + " xmlns=\"" + metaproxy_ns + "\">"
147                            + ", not " + got_element);
148     }
149     return true;
150 }
151
152 std::string mp_xml::get_route(const xmlNode *node)
153 {
154     std::string route_value;
155     if (node)
156     {
157         const struct _xmlAttr *attr;
158         for (attr = node->properties; attr; attr = attr->next)
159         {
160             std::string name = std::string((const char *) attr->name);
161             std::string value;
162             
163             if (attr->children && attr->children->type == XML_TEXT_NODE)
164                 value = std::string((const char *)attr->children->content);
165             
166             if (name == "route")
167                 route_value = value;
168             else
169                 throw XMLError("Only attribute route allowed"
170                                " in " + std::string((const char *)node->name)
171                                + " element. Got " + std::string(name));
172         }
173     }
174     return route_value;
175 }
176
177
178 const xmlNode* mp_xml::jump_to_children(const xmlNode* node,
179                                           int xml_node_type)
180 {
181     node = node->children;
182     for (; node && node->type != xml_node_type; node = node->next)
183         ;
184     return node;
185 }
186
187 const xmlNode* mp_xml::jump_to_next(const xmlNode* node,
188                                       int xml_node_type)
189 {
190     node = node->next;
191     for (; node && node->type != xml_node_type; node = node->next)
192         ;
193     return node;
194 }
195
196 const xmlNode* mp_xml::jump_to(const xmlNode* node,
197                                  int xml_node_type)
198 {
199     for (; node && node->type != xml_node_type; node = node->next)
200         ;
201     return node;
202 }
203
204 void mp_xml::check_empty(const xmlNode *node)
205 {
206     if (node)
207     {
208         const xmlNode *n;
209         const struct _xmlAttr *attr;
210         std::string extra;
211         for (attr = node->properties; attr; attr = attr->next)
212             if (!strcmp((const char *) attr->name, "type"))
213                 extra = " of type " + get_text(attr);
214         for (n = node->children; n; n = n->next)
215             if (n->type == XML_ELEMENT_NODE)
216                 throw mp::XMLError("No child elements allowed inside element "
217                                    + std::string((const char *) node->name)
218                                    + extra);
219     }
220 }
221
222 /*
223  * Local variables:
224  * c-basic-offset: 4
225  * c-file-style: "Stroustrup"
226  * indent-tabs-mode: nil
227  * End:
228  * vim: shiftwidth=4 tabstop=8 expandtab
229  */
230