1 /*
2 * Copyright (C) 2016 Jean-Luc Barriere
3 *
4 * This library is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation; either version 3, or (at your option)
7 * any later version.
8 *
9 * This library 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 Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; see the file COPYING. If not, write to
16 * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 */
21
22 #include "xmldict.h"
23 #include <string.h>
24
25 using namespace thumbnailer;
26
27 #define ZERO '\0'
28
PrefixEqual(const char * qname,const char * prefix)29 bool XMLNS::PrefixEqual(const char* qname, const char* prefix)
30 {
31 unsigned n = 0;
32 const char* p = qname;
33 while (*p != ZERO)
34 if (*(++p) == ':')
35 {
36 n = p - qname;
37 break;
38 }
39 return (strlen(prefix) == n && strncmp(qname, prefix, n) == 0);
40 }
41
NameEqual(const char * qname,const char * name)42 bool XMLNS::NameEqual(const char* qname, const char* name)
43 {
44 const char* n = qname;
45 const char* p = qname;
46 while (*p != ZERO)
47 if (*(++p) == ':')
48 {
49 n = p + 1;
50 break;
51 }
52 return (strcmp(n, name) == 0);
53 }
54
LocalName(const char * qname)55 const char* XMLNS::LocalName(const char* qname)
56 {
57 const char* n = qname;
58 const char* p = qname;
59 while (*p != ZERO)
60 if (*(++p) == ':')
61 {
62 n = p + 1;
63 break;
64 }
65 return n;
66 }
67
68 ///////////////////////////////////////////////////////////////////////////////
69 ////
70 //// XMLDict
71 ////
72
XMLDict()73 XMLDict::XMLDict()
74 {
75 }
76
DefineNS(const char * key,const char * name)77 void XMLDict::DefineNS(const char* key, const char* name)
78 {
79 // remove ending colon from key
80 std::string _key;
81 const char* p = key;
82 while (*p != ZERO && *p != ':') ++p;
83 if (p > key)
84 _key.assign(key, p - key);
85
86 XMLNS* ns = FindKey(_key.c_str());
87 if (ns)
88 {
89 ns->name.assign(name);
90 // rebuild xml string
91 m_xmlstring.assign(" ");
92 for (XMLNSList::iterator it = m_nsout.begin(); it != m_nsout.end(); ++it)
93 {
94 if (it->key.empty())
95 m_xmlstring.append("xmlns");
96 else
97 m_xmlstring.append("xmlns:").append(it->key);
98 m_xmlstring.append("=\"").append(it->name).append("\" ");
99 }
100 }
101 else
102 {
103 m_nsout.push_back(XMLNS(_key.c_str(), name));
104 // update xml string
105 XMLNS& xmlns = m_nsout.back();
106 if (m_xmlstring.empty())
107 m_xmlstring.assign(" ");
108 if (xmlns.key.empty())
109 m_xmlstring.append("xmlns");
110 else
111 m_xmlstring.append("xmlns:").append(xmlns.key);
112 m_xmlstring.append("=\"").append(xmlns.name).append("\" ");
113 }
114 }
115
KeyForName(const char * name)116 const char* XMLDict::KeyForName(const char* name)
117 {
118 XMLNSList::iterator it;
119 for (it = m_nsout.begin(); it != m_nsout.end(); ++it)
120 if (it->name.compare(name) == 0)
121 return it->key.c_str();
122 return 0;
123 }
124
TranslateQName(const XMLNames & names,const char * qname)125 std::string XMLDict::TranslateQName(const XMLNames& names, const char* qname)
126 {
127 unsigned l = 0;
128 const char* n = qname;
129 const char* p = qname;
130 while (*p != ZERO)
131 if (*(++p) == ':')
132 {
133 l = p - qname;
134 n = p + 1;
135 break;
136 }
137 std::string prefix(qname, l);
138 const XMLNS* in = names.FindKey(prefix.c_str());
139 if (in)
140 {
141 XMLNSList::const_iterator it;
142 for (it = m_nsout.begin(); it != m_nsout.end(); ++it)
143 if (it->name.compare(in->name) == 0)
144 {
145 if (it->key.empty())
146 return std::string(n); // return local name without qualifier
147 return std::string(it->key).append(":").append(n);
148 }
149 }
150 // cannot translate qualified name
151 return std::string(qname);
152 }
153
FindKey(const char * key)154 XMLNS* XMLDict::FindKey(const char* key)
155 {
156 XMLNSList::iterator it;
157 for (it = m_nsout.begin(); it != m_nsout.end(); ++it)
158 if (it->key.compare(key) == 0)
159 return &(*it);
160 return 0;
161 }
162
163 ///////////////////////////////////////////////////////////////////////////////
164 ////
165 //// XMLNames
166 ////
167
AddXMLNS(const tinyxml2::XMLElement * e)168 void XMLNames::AddXMLNS(const tinyxml2::XMLElement* e)
169 {
170 const tinyxml2::XMLAttribute* attr = e->FirstAttribute();
171 while (attr)
172 {
173 const char* key = 0;
174 if (XMLNS::PrefixEqual(attr->Name(), "xmlns"))
175 key = XMLNS::LocalName(attr->Name());
176 else if (XMLNS::NameEqual(attr->Name(), "xmlns"))
177 key = "";
178 if (key)
179 AddXMLNS(key, attr->Value());
180 attr = attr->Next();
181 }
182 }
183
AddXMLNS(const char * key,const char * name)184 void XMLNames::AddXMLNS(const char* key, const char* name)
185 {
186 XMLNS* ns = FindKey(key);
187 if (ns)
188 ns->name.assign(name);
189 else
190 m_names.push_back(XMLNS(key, name));
191 }
192
FindKey(const char * key)193 XMLNS* XMLNames::FindKey(const char* key)
194 {
195 XMLNSList::iterator it;
196 for (it = m_names.begin(); it != m_names.end(); ++it)
197 if (it->key.compare(key) == 0)
198 return &(*it);
199 return 0;
200 }
201
FindKey(const char * key) const202 const XMLNS* XMLNames::FindKey(const char* key) const
203 {
204 XMLNSList::const_iterator it;
205 for (it = m_names.begin(); it != m_names.end(); ++it)
206 if (it->key.compare(key) == 0)
207 return &(*it);
208 return 0;
209 }
210
FindName(const char * name)211 XMLNS* XMLNames::FindName(const char* name)
212 {
213 XMLNSList::iterator it;
214 for (it = m_names.begin(); it != m_names.end(); ++it)
215 if (it->name.compare(name) == 0)
216 return &(*it);
217 return 0;
218 }
219
FindName(const char * name) const220 const XMLNS* XMLNames::FindName(const char* name) const
221 {
222 XMLNSList::const_iterator it;
223 for (it = m_names.begin(); it != m_names.end(); ++it)
224 if (it->name.compare(name) == 0)
225 return &(*it);
226 return 0;
227 }
228