bes  Updated for version 3.20.6
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 using std::string;
33 
34 namespace ncml_module {
35 
37 
38 string XMLUtil::xmlCharToString(const xmlChar* theCharsOrNull)
39 {
40  const char* asChars = reinterpret_cast<const char*>(theCharsOrNull);
41  return ((asChars) ? (string(asChars)) : (string("")));
42 }
43 
44 void 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.
51 string 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 
63 XMLAttribute::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 
71 XMLAttribute::XMLAttribute(const xmlChar** chunkOfFivePointers)
72 {
73  fromSAX2NamespaceAttributes(chunkOfFivePointers);
74 }
75 
76 XMLAttribute::XMLAttribute(const XMLAttribute& proto) :
77  localname(proto.localname), prefix(proto.prefix), nsURI(proto.nsURI), value(proto.value)
78 {
79 }
80 
81 XMLAttribute&
82 XMLAttribute::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 
94 void 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 */
126 string 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 
137 XMLAttributeMap::XMLAttributeMap() :
138  _attributes()
139 {
140 }
141 
142 XMLAttributeMap::~XMLAttributeMap()
143 {
144 }
145 
146 XMLAttributeMap::const_iterator XMLAttributeMap::begin() const
147 {
148  return _attributes.begin();
149 }
150 
151 XMLAttributeMap::const_iterator XMLAttributeMap::end() const
152 {
153  return _attributes.end();
154 }
155 
156 bool 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 
180 const string /*& returns a reference to a local temp object (the else clause). jhrg 4/16/14*/
181 XMLAttributeMap::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 
193 const XMLAttribute*
194 XMLAttributeMap::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 
207 const XMLAttribute*
208 XMLAttributeMap::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 
221 const XMLAttribute*
222 XMLAttributeMap::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 
239 XMLAttributeMap::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 
252 XMLNamespace::XMLNamespace(const string& prefixArg/*=""*/, const string& uriArg/*=""*/) :
253  prefix(prefixArg), uri(uriArg)
254 {
255 }
256 
257 XMLNamespace::XMLNamespace(const XMLNamespace& proto) :
258  prefix(proto.prefix), uri(proto.uri)
259 {
260 }
261 
262 XMLNamespace&
263 XMLNamespace::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 
274 void 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 
295 XMLNamespaceMap::XMLNamespaceMap() :
296  _namespaces()
297 {
298 }
299 
300 XMLNamespaceMap::~XMLNamespaceMap()
301 {
302  _namespaces.clear();
303 }
304 
305 XMLNamespaceMap::XMLNamespaceMap(const XMLNamespaceMap& proto) :
306  _namespaces(proto._namespaces)
307 {
308 }
309 
310 XMLNamespaceMap&
311 XMLNamespaceMap::operator=(const XMLNamespaceMap& rhs)
312 {
313  if (this == &rhs) {
314  return *this;
315  }
316  _namespaces = rhs._namespaces;
317  return *this;
318 }
319 
320 void 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 
341 XMLNamespaceMap::const_iterator XMLNamespaceMap::begin() const
342 {
343  return _namespaces.begin();
344 }
345 
346 XMLNamespaceMap::const_iterator XMLNamespaceMap::end() const
347 {
348  return _namespaces.end();
349 }
350 
351 XMLNamespaceMap::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 
362 bool 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 
380 void XMLNamespaceMap::clear()
381 {
382  _namespaces.clear();
383 }
384 
385 bool XMLNamespaceMap::empty() const
386 {
387  return _namespaces.empty();
388 }
389 
390 XMLNamespaceMap::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 
403 XMLNamespaceStack::XMLNamespaceStack() :
404  _stack()
405 {
406 }
407 
408 XMLNamespaceStack::~XMLNamespaceStack()
409 {
410  _stack.clear();
411  _stack.resize(0);
412 }
413 
414 XMLNamespaceStack::XMLNamespaceStack(const XMLNamespaceStack& proto) :
415  _stack(proto._stack)
416 {
417 }
418 
419 XMLNamespaceStack&
420 XMLNamespaceStack::operator=(const XMLNamespaceStack& rhs)
421 {
422  if (this == &rhs) {
423  return *this;
424  }
425  _stack = rhs._stack;
426  return *this;
427 }
428 
429 void XMLNamespaceStack::push(const XMLNamespaceMap& nsMap)
430 {
431  _stack.push_back(nsMap);
432 }
433 
434 void XMLNamespaceStack::pop()
435 {
436  _stack.pop_back();
437 }
438 
439 const XMLNamespaceMap&
440 XMLNamespaceStack::top() const
441 {
442  return _stack.back();
443 }
444 
445 bool XMLNamespaceStack::empty() const
446 {
447  return _stack.empty();
448 }
449 
450 void XMLNamespaceStack::clear()
451 {
452  _stack.clear();
453 }
454 
455 XMLNamespaceStack::const_iterator XMLNamespaceStack::begin() const
456 {
457  return _stack.rbegin();
458 }
459 
460 XMLNamespaceStack::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 */
475 void 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 ;
488 // namespace ncml_module
ncml_module::XMLAttributeMap::getAllAttributesAsString
std::string getAllAttributesAsString() const
Definition: XMLHelpers.cc:228
ncml_module::XMLNamespace
Definition: XMLHelpers.h:135
ncml_module::XMLAttribute::fromSAX2NamespaceAttributes
void fromSAX2NamespaceAttributes(const xmlChar **chunkOfFivePointers)
Definition: XMLHelpers.cc:94
ncml_module::XMLNamespaceMap::fromSAX2Namespaces
void fromSAX2Namespaces(const xmlChar **pNamespaces, int numNamespaces)
Definition: XMLHelpers.cc:320
ncml_module::XMLNamespaceMap::getAllNamespacesAsAttributeString
std::string getAllNamespacesAsAttributeString() const
Definition: XMLHelpers.cc:331
ncml_module::XMLNamespaceMap::addNamespace
void addNamespace(const XMLNamespace &ns)
Definition: XMLHelpers.cc:367
ncml_module::XMLAttributeMap::getAttributeByLocalName
const XMLAttribute * getAttributeByLocalName(const std::string &localname) const
Definition: XMLHelpers.cc:194
ncml_module::XMLAttributeMap::addAttribute
void addAttribute(const XMLAttribute &attribute)
Definition: XMLHelpers.cc:167
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:58
ncml_module::XMLAttribute::getQName
std::string getQName() const
Definition: XMLHelpers.cc:111
ncml_module::XMLNamespace::getAsAttributeString
std::string getAsAttributeString() const
Definition: XMLHelpers.cc:281
ncml_module::XMLAttributeMap::getValueForLocalNameOrDefault
const std::string getValueForLocalNameOrDefault(const std::string &localname, const std::string &defVal="") const
Definition: XMLHelpers.cc:181
ncml_module::XMLNamespaceMap
Definition: XMLHelpers.h:150
ncml_module::XMLAttribute::getAsXMLString
std::string getAsXMLString() const
Definition: XMLHelpers.cc:120
ncml_module::XMLNamespaceMap::find
XMLNamespaceMap::const_iterator find(const std::string &prefix) const
Definition: XMLHelpers.cc:351
ncml_module::XMLNamespace::fromSAX2Namespace
void fromSAX2Namespace(const xmlChar **namespaces)
Definition: XMLHelpers.cc:274
ncml_module::XMLNamespaceStack::getFlattenedNamespacesUsingLexicalScoping
void getFlattenedNamespacesUsingLexicalScoping(XMLNamespaceMap &nsFlattened) const
Definition: XMLHelpers.cc:465
ncml_module::XMLAttributeMap::clear
void clear()
Definition: XMLHelpers.cc:161
ncml_module::XMLNamespaceStack::begin
XMLNamespaceStack::const_iterator begin() const
Definition: XMLHelpers.cc:455