bes  Updated for version 3.20.5
XMLHelpers.cc
1 // 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 
32 namespace ncml_module {
33 
35 
36 string XMLUtil::xmlCharToString(const xmlChar* theCharsOrNull)
37 {
38  const char* asChars = reinterpret_cast<const char*>(theCharsOrNull);
39  return ((asChars) ? (string(asChars)) : (string("")));
40 }
41 
42 void XMLUtil::xmlCharToString(string& stringToFill, const xmlChar* pChars)
43 {
44  stringToFill = xmlCharToString(pChars);
45 }
46 
47 // Interpret the args as the start and stop iterator of chars.
48 // But check for empty on it.
49 string XMLUtil::xmlCharToStringFromIterators(const xmlChar* startIter, const xmlChar* endIter)
50 {
51  // Just be safe, no use for exceptions.
52  if (!startIter || !endIter || (startIter > endIter)) {
53  return string("");
54  }
55 
56  // These are interpreted as const char* iterators.
57  return string(reinterpret_cast<const char*>(startIter), reinterpret_cast<const char*>(endIter));
58 }
59 
61 XMLAttribute::XMLAttribute(const string& localNameA, const string& valueA, const string& prefixA, const string& nsURIA) :
62  localname(localNameA), prefix(prefixA), nsURI(nsURIA), value(valueA)
63 {
64 }
65 
69 XMLAttribute::XMLAttribute(const xmlChar** chunkOfFivePointers)
70 {
71  fromSAX2NamespaceAttributes(chunkOfFivePointers);
72 }
73 
74 XMLAttribute::XMLAttribute(const XMLAttribute& proto) :
75  localname(proto.localname), prefix(proto.prefix), nsURI(proto.nsURI), value(proto.value)
76 {
77 }
78 
79 XMLAttribute&
80 XMLAttribute::operator=(const XMLAttribute& rhs)
81 {
82  if (&rhs == this) {
83  return *this;
84  }
85  localname = rhs.localname;
86  prefix = rhs.prefix;
87  value = rhs.value;
88  nsURI = rhs.nsURI; // jhrg 3/16/11
89  return *this;
90 }
91 
92 void XMLAttribute::fromSAX2NamespaceAttributes(const xmlChar** chunkOfFivePointers)
93 {
94  const xmlChar* xmlLocalName = (*chunkOfFivePointers++);
95  const xmlChar* xmlPrefix = (*chunkOfFivePointers++);
96  const xmlChar* xmlURI = (*chunkOfFivePointers++);
97  const xmlChar* xmlValueStart = (*chunkOfFivePointers++);
98  // pointer to end of the value since not null terminated.
99  const xmlChar* xmlValueEnd = (*chunkOfFivePointers++);
100 
101  // makeString calls map null into "".
102  localname = XMLUtil::xmlCharToString(xmlLocalName);
103  prefix = XMLUtil::xmlCharToString(xmlPrefix);
104  nsURI = XMLUtil::xmlCharToString(xmlURI);
105  value = XMLUtil::xmlCharToStringFromIterators(xmlValueStart, xmlValueEnd);
106 }
107 
110 {
111  return getQName(prefix, localname);
112 }
113 
119 {
120  return getQName() + "=\"" + value + "\"";
121 }
122 
123 /*static */
124 string XMLAttribute::getQName(const string& prefix, const string& localname)
125 {
126  if (prefix.empty()) {
127  return localname;
128  }
129  else {
130  return prefix + ":" + localname;
131  }
132 }
133 
135 XMLAttributeMap::XMLAttributeMap() :
136  _attributes()
137 {
138 }
139 
140 XMLAttributeMap::~XMLAttributeMap()
141 {
142 }
143 
144 XMLAttributeMap::const_iterator XMLAttributeMap::begin() const
145 {
146  return _attributes.begin();
147 }
148 
149 XMLAttributeMap::const_iterator XMLAttributeMap::end() const
150 {
151  return _attributes.end();
152 }
153 
154 bool XMLAttributeMap::empty() const
155 {
156  return _attributes.empty();
157 }
158 
160 {
161  // won't resize, we might be reusing it so no point.
162  _attributes.clear();
163 }
164 
166 {
167  XMLAttributeMap::iterator foundIt = findByQName(attribute.getQName());
168  // if in there, replace it.
169  if (foundIt != _attributes.end()) {
170  // replace with a copy of new one
171  (*foundIt) = XMLAttribute(attribute);
172  }
173 
174  // otherwise push on a new one
175  _attributes.push_back(attribute);
176 }
177 
178 const string /*& returns a reference to a local temp object (the else clause). jhrg 4/16/14*/
179 XMLAttributeMap::getValueForLocalNameOrDefault(const string& localname, const string& defVal/*=""*/) const
180 {
181  const XMLAttribute* pAttr = getAttributeByLocalName(localname);
182  if (pAttr) {
183  return pAttr->value;
184  }
185  else {
186  // Reference to a local temporary object. jhrg 4/16/14
187  return defVal;
188  }
189 }
190 
191 const XMLAttribute*
192 XMLAttributeMap::getAttributeByLocalName(const string& localname) const
193 {
194  const XMLAttribute* pAtt = 0; // if not found
195  for (XMLAttributeMap::const_iterator it = begin(); it != end(); ++it) {
196  const XMLAttribute& rAttr = *it;
197  if (rAttr.localname == localname) {
198  pAtt = &rAttr;
199  break;
200  }
201  }
202  return pAtt;
203 }
204 
205 const XMLAttribute*
206 XMLAttributeMap::getAttributeByQName(const string& qname) const
207 {
208  const XMLAttribute* pAtt = 0; // if not found
209  for (XMLAttributeMap::const_iterator it = begin(); it != end(); ++it) {
210  const XMLAttribute& rAttr = *it;
211  if (rAttr.getQName() == qname) {
212  pAtt = &rAttr;
213  break;
214  }
215  }
216  return pAtt;
217 }
218 
219 const XMLAttribute*
220 XMLAttributeMap::getAttributeByQName(const string& prefix, const string& localname) const
221 {
222  return getAttributeByQName(XMLAttribute::getQName(prefix, localname));
223 }
224 
227 {
228  string result("");
229  XMLAttributeMap::const_iterator it;
230  for (it = begin(); it != end(); ++it) {
231  const XMLAttribute& attr = *it;
232  result += (attr.getQName() + "=\"" + attr.value + "\" ");
233  }
234  return result;
235 }
236 
237 XMLAttributeMap::iterator XMLAttributeMap::findByQName(const string& qname)
238 {
239  XMLAttributeMap::iterator it;
240  for (it = _attributes.begin(); it != _attributes.end(); ++it) {
241  if (it->getQName() == qname) {
242  break;
243  }
244  }
245  return it;
246 }
247 
249 
250 XMLNamespace::XMLNamespace(const string& prefixArg/*=""*/, const string& uriArg/*=""*/) :
251  prefix(prefixArg), uri(uriArg)
252 {
253 }
254 
255 XMLNamespace::XMLNamespace(const XMLNamespace& proto) :
256  prefix(proto.prefix), uri(proto.uri)
257 {
258 }
259 
260 XMLNamespace&
261 XMLNamespace::operator=(const XMLNamespace& rhs)
262 {
263  if (this == &rhs) {
264  return *this;
265  }
266 
267  prefix = rhs.prefix;
268  uri = rhs.uri;
269  return *this;
270 }
271 
272 void XMLNamespace::fromSAX2Namespace(const xmlChar** pNamespace)
273 {
274  prefix = XMLUtil::xmlCharToString(*pNamespace);
275  uri = XMLUtil::xmlCharToString(*(pNamespace + 1));
276 }
277 
280 {
281  string attr("xmlns");
282  if (!prefix.empty()) {
283  attr += (string(":") + prefix);
284  }
285  attr += string("=\"");
286  attr += uri;
287  attr += string("\"");
288  return attr;
289 }
290 
292 
293 XMLNamespaceMap::XMLNamespaceMap() :
294  _namespaces()
295 {
296 }
297 
298 XMLNamespaceMap::~XMLNamespaceMap()
299 {
300  _namespaces.clear();
301 }
302 
303 XMLNamespaceMap::XMLNamespaceMap(const XMLNamespaceMap& proto) :
304  _namespaces(proto._namespaces)
305 {
306 }
307 
308 XMLNamespaceMap&
309 XMLNamespaceMap::operator=(const XMLNamespaceMap& rhs)
310 {
311  if (this == &rhs) {
312  return *this;
313  }
314  _namespaces = rhs._namespaces;
315  return *this;
316 }
317 
318 void XMLNamespaceMap::fromSAX2Namespaces(const xmlChar** pNamespaces, int numNamespaces)
319 {
320  clear();
321  for (int i = 0; i < numNamespaces; ++i) {
322  XMLNamespace ns;
323  ns.fromSAX2Namespace(pNamespaces);
324  pNamespaces += 2; // this array is stride 2
325  addNamespace(ns);
326  }
327 }
328 
330 {
331  string allAttrs("");
332  for (XMLNamespaceMap::const_iterator it = begin(); it != end(); ++it) {
333  const XMLNamespace& ns = *it;
334  allAttrs += string(" ") + ns.getAsAttributeString();
335  }
336  return allAttrs;
337 }
338 
339 XMLNamespaceMap::const_iterator XMLNamespaceMap::begin() const
340 {
341  return _namespaces.begin();
342 }
343 
344 XMLNamespaceMap::const_iterator XMLNamespaceMap::end() const
345 {
346  return _namespaces.end();
347 }
348 
349 XMLNamespaceMap::const_iterator XMLNamespaceMap::find(const string& prefix) const
350 {
351  XMLNamespaceMap::const_iterator foundIt;
352  for (foundIt = begin(); foundIt != end(); ++foundIt) {
353  if (foundIt->prefix == prefix) {
354  break;
355  }
356  }
357  return foundIt;
358 }
359 
360 bool XMLNamespaceMap::isInMap(const string& prefix) const
361 {
362  return (find(prefix) != end());
363 }
364 
366 {
367  XMLNamespaceMap::iterator foundIt = findNonConst(ns.prefix);
368  if (foundIt == _namespaces.end()) // not found, push
369  {
370  _namespaces.push_back(ns);
371  }
372  else {
373  // overwrite
374  (*foundIt) = XMLNamespace(ns);
375  }
376 }
377 
378 void XMLNamespaceMap::clear()
379 {
380  _namespaces.clear();
381 }
382 
383 bool XMLNamespaceMap::empty() const
384 {
385  return _namespaces.empty();
386 }
387 
388 XMLNamespaceMap::iterator XMLNamespaceMap::findNonConst(const string& prefix)
389 {
390  XMLNamespaceMap::iterator foundIt;
391  for (foundIt = _namespaces.begin(); foundIt != _namespaces.end(); ++foundIt) {
392  if (foundIt->prefix == prefix) {
393  break;
394  }
395  }
396  return foundIt;
397 }
398 
400 
401 XMLNamespaceStack::XMLNamespaceStack() :
402  _stack()
403 {
404 }
405 
406 XMLNamespaceStack::~XMLNamespaceStack()
407 {
408  _stack.clear();
409  _stack.resize(0);
410 }
411 
412 XMLNamespaceStack::XMLNamespaceStack(const XMLNamespaceStack& proto) :
413  _stack(proto._stack)
414 {
415 }
416 
417 XMLNamespaceStack&
418 XMLNamespaceStack::operator=(const XMLNamespaceStack& rhs)
419 {
420  if (this == &rhs) {
421  return *this;
422  }
423  _stack = rhs._stack;
424  return *this;
425 }
426 
427 void XMLNamespaceStack::push(const XMLNamespaceMap& nsMap)
428 {
429  _stack.push_back(nsMap);
430 }
431 
432 void XMLNamespaceStack::pop()
433 {
434  _stack.pop_back();
435 }
436 
437 const XMLNamespaceMap&
438 XMLNamespaceStack::top() const
439 {
440  return _stack.back();
441 }
442 
443 bool XMLNamespaceStack::empty() const
444 {
445  return _stack.empty();
446 }
447 
448 void XMLNamespaceStack::clear()
449 {
450  _stack.clear();
451 }
452 
453 XMLNamespaceStack::const_iterator XMLNamespaceStack::begin() const
454 {
455  return _stack.rbegin();
456 }
457 
458 XMLNamespaceStack::const_iterator XMLNamespaceStack::end() const
459 {
460  return _stack.rend();
461 }
462 
464 {
465  // Scan the stack in top (lexically innermost) to bottom order, adding in
466  // the namespaces we don't have a prefix for.
467  for (XMLNamespaceStack::const_iterator it = begin(); it != end(); ++it) {
468  addMissingNamespaces(nsFlattened, *it);
469  }
470 }
471 
472 /* static */
473 void XMLNamespaceStack::addMissingNamespaces(XMLNamespaceMap& intoMap, const XMLNamespaceMap& fromMap)
474 {
475  for (XMLNamespaceMap::const_iterator it = fromMap.begin(); it != fromMap.end(); ++it) {
476  const XMLNamespace& ns = *it;
477  // If this namespace is not in the output map, add it
478  if (intoMap.find(ns.prefix) == intoMap.end()) {
479  intoMap.addNamespace(ns);
480  }
481  // otherwise, it's been lexically shadowed, so ignore it.
482  }
483 }
484 }
485 ;
486 // namespace ncml_module
ncml_module::XMLAttributeMap::getAllAttributesAsString
string getAllAttributesAsString() const
Definition: XMLHelpers.cc:226
ncml_module::XMLNamespace
Definition: XMLHelpers.h:138
ncml_module::XMLAttribute::fromSAX2NamespaceAttributes
void fromSAX2NamespaceAttributes(const xmlChar **chunkOfFivePointers)
Definition: XMLHelpers.cc:92
ncml_module::XMLNamespaceMap::fromSAX2Namespaces
void fromSAX2Namespaces(const xmlChar **pNamespaces, int numNamespaces)
Definition: XMLHelpers.cc:318
ncml_module::XMLNamespaceMap::getAllNamespacesAsAttributeString
string getAllNamespacesAsAttributeString() const
Definition: XMLHelpers.cc:329
ncml_module::XMLNamespaceMap::addNamespace
void addNamespace(const XMLNamespace &ns)
Definition: XMLHelpers.cc:365
ncml_module::XMLNamespaceMap::find
XMLNamespaceMap::const_iterator find(const string &prefix) const
Definition: XMLHelpers.cc:349
ncml_module::XMLAttributeMap::addAttribute
void addAttribute(const XMLAttribute &attribute)
Definition: XMLHelpers.cc:165
ncml_module
NcML Parser for adding/modifying/removing metadata (attributes) to existing local datasets using NcML...
Definition: AggregationElement.cc:72
ncml_module::XMLAttribute
Definition: XMLHelpers.h:61
ncml_module::XMLAttribute::getQName
string getQName() const
Definition: XMLHelpers.cc:109
ncml_module::XMLNamespace::getAsAttributeString
string getAsAttributeString() const
Definition: XMLHelpers.cc:279
ncml_module::XMLNamespaceMap
Definition: XMLHelpers.h:153
ncml_module::XMLAttribute::getAsXMLString
string getAsXMLString() const
Definition: XMLHelpers.cc:118
ncml_module::XMLAttributeMap::getValueForLocalNameOrDefault
const string getValueForLocalNameOrDefault(const string &localname, const string &defVal="") const
Definition: XMLHelpers.cc:179
ncml_module::XMLNamespace::fromSAX2Namespace
void fromSAX2Namespace(const xmlChar **namespaces)
Definition: XMLHelpers.cc:272
ncml_module::XMLNamespaceStack::getFlattenedNamespacesUsingLexicalScoping
void getFlattenedNamespacesUsingLexicalScoping(XMLNamespaceMap &nsFlattened) const
Definition: XMLHelpers.cc:463
ncml_module::XMLAttributeMap::clear
void clear()
Definition: XMLHelpers.cc:159
ncml_module::XMLNamespaceStack::begin
XMLNamespaceStack::const_iterator begin() const
Definition: XMLHelpers.cc:453
ncml_module::XMLAttributeMap::getAttributeByLocalName
const XMLAttribute * getAttributeByLocalName(const string &localname) const
Definition: XMLHelpers.cc:192