bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
XMLHelpers.cc
1
2// This file is part of the "NcML Module" project, a BES module designed
3// to allow NcML files to be used to be used as a wrapper to add
4// AIS to existing datasets of any format.
5//
6// Copyright (c) 2009 OPeNDAP, Inc.
7// Author: Michael Johnson <m.johnson@opendap.org>
8//
9// For more information, please also see the main website: http://opendap.org/
10//
11// This library is free software; you can redistribute it and/or
12// modify it under the terms of the GNU Lesser General Public
13// License as published by the Free Software Foundation; either
14// version 2.1 of the License, or (at your option) any later version.
15//
16// This library is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19// Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public
22// License along with this library; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24//
25// Please see the files COPYING and COPYRIGHT for more information on the GLPL.
26//
27// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
29
30#include "XMLHelpers.h"
31
32using std::string;
33
34namespace ncml_module {
35
37
38string XMLUtil::xmlCharToString(const xmlChar* theCharsOrNull)
39{
40 const char* asChars = reinterpret_cast<const char*>(theCharsOrNull);
41 return ((asChars) ? (string(asChars)) : (string("")));
42}
43
44void XMLUtil::xmlCharToString(string& stringToFill, const xmlChar* pChars)
45{
46 stringToFill = xmlCharToString(pChars);
47}
48
49// Interpret the args as the start and stop iterator of chars.
50// But check for empty on it.
51string XMLUtil::xmlCharToStringFromIterators(const xmlChar* startIter, const xmlChar* endIter)
52{
53 // Just be safe, no use for exceptions.
54 if (!startIter || !endIter || (startIter > endIter)) {
55 return string("");
56 }
57
58 // These are interpreted as const char* iterators.
59 return string(reinterpret_cast<const char*>(startIter), reinterpret_cast<const char*>(endIter));
60}
61
63XMLAttribute::XMLAttribute(const string& localNameA, const string& valueA, const string& prefixA, const string& nsURIA) :
64 localname(localNameA), prefix(prefixA), nsURI(nsURIA), value(valueA)
65{
66}
67
71XMLAttribute::XMLAttribute(const xmlChar** chunkOfFivePointers)
72{
73 fromSAX2NamespaceAttributes(chunkOfFivePointers);
74}
75
76XMLAttribute::XMLAttribute(const XMLAttribute& proto) :
77 localname(proto.localname), prefix(proto.prefix), nsURI(proto.nsURI), value(proto.value)
78{
79}
80
81XMLAttribute&
82XMLAttribute::operator=(const XMLAttribute& rhs)
83{
84 if (&rhs == this) {
85 return *this;
86 }
87 localname = rhs.localname;
88 prefix = rhs.prefix;
89 value = rhs.value;
90 nsURI = rhs.nsURI; // jhrg 3/16/11
91 return *this;
92}
93
94void XMLAttribute::fromSAX2NamespaceAttributes(const xmlChar** chunkOfFivePointers)
95{
96 const xmlChar* xmlLocalName = (*chunkOfFivePointers++);
97 const xmlChar* xmlPrefix = (*chunkOfFivePointers++);
98 const xmlChar* xmlURI = (*chunkOfFivePointers++);
99 const xmlChar* xmlValueStart = (*chunkOfFivePointers++);
100 // pointer to end of the value since not null terminated.
101 const xmlChar* xmlValueEnd = (*chunkOfFivePointers++);
102
103 // makeString calls map null into "".
104 localname = XMLUtil::xmlCharToString(xmlLocalName);
105 prefix = XMLUtil::xmlCharToString(xmlPrefix);
106 nsURI = XMLUtil::xmlCharToString(xmlURI);
107 value = XMLUtil::xmlCharToStringFromIterators(xmlValueStart, xmlValueEnd);
108}
109
112{
113 return getQName(prefix, localname);
114}
115
121{
122 return getQName() + "=\"" + value + "\"";
123}
124
125/*static */
126string XMLAttribute::getQName(const string& prefix, const string& localname)
127{
128 if (prefix.empty()) {
129 return localname;
130 }
131 else {
132 return prefix + ":" + localname;
133 }
134}
135
137XMLAttributeMap::XMLAttributeMap() :
138 _attributes()
139{
140}
141
142XMLAttributeMap::~XMLAttributeMap()
143{
144}
145
146XMLAttributeMap::const_iterator XMLAttributeMap::begin() const
147{
148 return _attributes.begin();
149}
150
151XMLAttributeMap::const_iterator XMLAttributeMap::end() const
152{
153 return _attributes.end();
154}
155
156bool XMLAttributeMap::empty() const
157{
158 return _attributes.empty();
159}
160
162{
163 // won't resize, we might be reusing it so no point.
164 _attributes.clear();
165}
166
168{
169 XMLAttributeMap::iterator foundIt = findByQName(attribute.getQName());
170 // if in there, replace it.
171 if (foundIt != _attributes.end()) {
172 // replace with a copy of new one
173 (*foundIt) = XMLAttribute(attribute);
174 }
175
176 // otherwise push on a new one
177 _attributes.push_back(attribute);
178}
179
180const string /*& returns a reference to a local temp object (the else clause). jhrg 4/16/14*/
181XMLAttributeMap::getValueForLocalNameOrDefault(const string& localname, const string& defVal/*=""*/) const
182{
183 const XMLAttribute* pAttr = getAttributeByLocalName(localname);
184 if (pAttr) {
185 return pAttr->value;
186 }
187 else {
188 // Reference to a local temporary object. jhrg 4/16/14
189 return defVal;
190 }
191}
192
193const XMLAttribute*
194XMLAttributeMap::getAttributeByLocalName(const string& localname) const
195{
196 const XMLAttribute* pAtt = 0; // if not found
197 for (XMLAttributeMap::const_iterator it = begin(); it != end(); ++it) {
198 const XMLAttribute& rAttr = *it;
199 if (rAttr.localname == localname) {
200 pAtt = &rAttr;
201 break;
202 }
203 }
204 return pAtt;
205}
206
207const XMLAttribute*
208XMLAttributeMap::getAttributeByQName(const string& qname) const
209{
210 const XMLAttribute* pAtt = 0; // if not found
211 for (XMLAttributeMap::const_iterator it = begin(); it != end(); ++it) {
212 const XMLAttribute& rAttr = *it;
213 if (rAttr.getQName() == qname) {
214 pAtt = &rAttr;
215 break;
216 }
217 }
218 return pAtt;
219}
220
221const XMLAttribute*
222XMLAttributeMap::getAttributeByQName(const string& prefix, const string& localname) const
223{
224 return getAttributeByQName(XMLAttribute::getQName(prefix, localname));
225}
226
229{
230 string result("");
231 XMLAttributeMap::const_iterator it;
232 for (it = begin(); it != end(); ++it) {
233 const XMLAttribute& attr = *it;
234 result += (attr.getQName() + "=\"" + attr.value + "\" ");
235 }
236 return result;
237}
238
239XMLAttributeMap::iterator XMLAttributeMap::findByQName(const string& qname)
240{
241 XMLAttributeMap::iterator it;
242 for (it = _attributes.begin(); it != _attributes.end(); ++it) {
243 if (it->getQName() == qname) {
244 break;
245 }
246 }
247 return it;
248}
249
251
252XMLNamespace::XMLNamespace(const string& prefixArg/*=""*/, const string& uriArg/*=""*/) :
253 prefix(prefixArg), uri(uriArg)
254{
255}
256
257XMLNamespace::XMLNamespace(const XMLNamespace& proto) :
258 prefix(proto.prefix), uri(proto.uri)
259{
260}
261
263XMLNamespace::operator=(const XMLNamespace& rhs)
264{
265 if (this == &rhs) {
266 return *this;
267 }
268
269 prefix = rhs.prefix;
270 uri = rhs.uri;
271 return *this;
272}
273
274void XMLNamespace::fromSAX2Namespace(const xmlChar** pNamespace)
275{
276 prefix = XMLUtil::xmlCharToString(*pNamespace);
277 uri = XMLUtil::xmlCharToString(*(pNamespace + 1));
278}
279
282{
283 string attr("xmlns");
284 if (!prefix.empty()) {
285 attr += (string(":") + prefix);
286 }
287 attr += string("=\"");
288 attr += uri;
289 attr += string("\"");
290 return attr;
291}
292
294
295XMLNamespaceMap::XMLNamespaceMap() :
296 _namespaces()
297{
298}
299
300XMLNamespaceMap::~XMLNamespaceMap()
301{
302 _namespaces.clear();
303}
304
305XMLNamespaceMap::XMLNamespaceMap(const XMLNamespaceMap& proto) :
306 _namespaces(proto._namespaces)
307{
308}
309
311XMLNamespaceMap::operator=(const XMLNamespaceMap& rhs)
312{
313 if (this == &rhs) {
314 return *this;
315 }
316 _namespaces = rhs._namespaces;
317 return *this;
318}
319
320void XMLNamespaceMap::fromSAX2Namespaces(const xmlChar** pNamespaces, int numNamespaces)
321{
322 clear();
323 for (int i = 0; i < numNamespaces; ++i) {
324 XMLNamespace ns;
325 ns.fromSAX2Namespace(pNamespaces);
326 pNamespaces += 2; // this array is stride 2
327 addNamespace(ns);
328 }
329}
330
332{
333 string allAttrs("");
334 for (XMLNamespaceMap::const_iterator it = begin(); it != end(); ++it) {
335 const XMLNamespace& ns = *it;
336 allAttrs += string(" ") + ns.getAsAttributeString();
337 }
338 return allAttrs;
339}
340
341XMLNamespaceMap::const_iterator XMLNamespaceMap::begin() const
342{
343 return _namespaces.begin();
344}
345
346XMLNamespaceMap::const_iterator XMLNamespaceMap::end() const
347{
348 return _namespaces.end();
349}
350
351XMLNamespaceMap::const_iterator XMLNamespaceMap::find(const string& prefix) const
352{
353 XMLNamespaceMap::const_iterator foundIt;
354 for (foundIt = begin(); foundIt != end(); ++foundIt) {
355 if (foundIt->prefix == prefix) {
356 break;
357 }
358 }
359 return foundIt;
360}
361
362bool XMLNamespaceMap::isInMap(const string& prefix) const
363{
364 return (find(prefix) != end());
365}
366
368{
369 XMLNamespaceMap::iterator foundIt = findNonConst(ns.prefix);
370 if (foundIt == _namespaces.end()) // not found, push
371 {
372 _namespaces.push_back(ns);
373 }
374 else {
375 // overwrite
376 (*foundIt) = XMLNamespace(ns);
377 }
378}
379
380void XMLNamespaceMap::clear()
381{
382 _namespaces.clear();
383}
384
385bool XMLNamespaceMap::empty() const
386{
387 return _namespaces.empty();
388}
389
390XMLNamespaceMap::iterator XMLNamespaceMap::findNonConst(const string& prefix)
391{
392 XMLNamespaceMap::iterator foundIt;
393 for (foundIt = _namespaces.begin(); foundIt != _namespaces.end(); ++foundIt) {
394 if (foundIt->prefix == prefix) {
395 break;
396 }
397 }
398 return foundIt;
399}
400
402
403XMLNamespaceStack::XMLNamespaceStack() :
404 _stack()
405{
406}
407
408XMLNamespaceStack::~XMLNamespaceStack()
409{
410 _stack.clear();
411 _stack.resize(0);
412}
413
414XMLNamespaceStack::XMLNamespaceStack(const XMLNamespaceStack& proto) :
415 _stack(proto._stack)
416{
417}
418
420XMLNamespaceStack::operator=(const XMLNamespaceStack& rhs)
421{
422 if (this == &rhs) {
423 return *this;
424 }
425 _stack = rhs._stack;
426 return *this;
427}
428
429void XMLNamespaceStack::push(const XMLNamespaceMap& nsMap)
430{
431 _stack.push_back(nsMap);
432}
433
434void XMLNamespaceStack::pop()
435{
436 _stack.pop_back();
437}
438
439const XMLNamespaceMap&
440XMLNamespaceStack::top() const
441{
442 return _stack.back();
443}
444
445bool XMLNamespaceStack::empty() const
446{
447 return _stack.empty();
448}
449
450void XMLNamespaceStack::clear()
451{
452 _stack.clear();
453}
454
455XMLNamespaceStack::const_iterator XMLNamespaceStack::begin() const
456{
457 return _stack.rbegin();
458}
459
460XMLNamespaceStack::const_iterator XMLNamespaceStack::end() const
461{
462 return _stack.rend();
463}
464
466{
467 // Scan the stack in top (lexically innermost) to bottom order, adding in
468 // the namespaces we don't have a prefix for.
469 for (XMLNamespaceStack::const_iterator it = begin(); it != end(); ++it) {
470 addMissingNamespaces(nsFlattened, *it);
471 }
472}
473
474/* static */
475void XMLNamespaceStack::addMissingNamespaces(XMLNamespaceMap& intoMap, const XMLNamespaceMap& fromMap)
476{
477 for (XMLNamespaceMap::const_iterator it = fromMap.begin(); it != fromMap.end(); ++it) {
478 const XMLNamespace& ns = *it;
479 // If this namespace is not in the output map, add it
480 if (intoMap.find(ns.prefix) == intoMap.end()) {
481 intoMap.addNamespace(ns);
482 }
483 // otherwise, it's been lexically shadowed, so ignore it.
484 }
485}
486}
487// namespace ncml_module
const std::string getValueForLocalNameOrDefault(const std::string &localname, const std::string &defVal="") const
const XMLAttribute * getAttributeByLocalName(const std::string &localname) const
void addAttribute(const XMLAttribute &attribute)
std::string getAllAttributesAsString() const
void fromSAX2Namespaces(const xmlChar **pNamespaces, int numNamespaces)
std::string getAllNamespacesAsAttributeString() const
void addNamespace(const XMLNamespace &ns)
XMLNamespaceMap::const_iterator find(const std::string &prefix) const
void getFlattenedNamespacesUsingLexicalScoping(XMLNamespaceMap &nsFlattened) const
XMLNamespaceStack::const_iterator begin() const
NcML Parser for adding/modifying/removing metadata (attributes) to existing local datasets using NcML...
std::string getAsXMLString() const
std::string getQName() const
void fromSAX2NamespaceAttributes(const xmlChar **chunkOfFivePointers)
Definition XMLHelpers.cc:94
std::string getAsAttributeString() const
void fromSAX2Namespace(const xmlChar **namespaces)