OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
XMLHelpers.cc
Go to the documentation of this file.
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 {
34 
36 
37  string
38  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
45  XMLUtil::xmlCharToString(string& stringToFill, const xmlChar* pChars)
46  {
47  stringToFill = xmlCharToString(pChars);
48  }
49 
50  // Interpret the args as the start and stop iterator of chars.
51  // But check for empty on it.
52  string
53  XMLUtil::xmlCharToStringFromIterators(const xmlChar* startIter, const xmlChar* endIter)
54  {
55  // Just be safe, no use for exceptions.
56  if (!startIter || !endIter || (startIter > endIter) )
57  {
58  return string("");
59  }
60 
61  // These are interpreted as const char* iterators.
62  return string(
63  reinterpret_cast<const char*>(startIter),
64  reinterpret_cast<const char*>(endIter));
65  }
66 
67 
69  XMLAttribute::XMLAttribute(const string& localNameA,
70  const string& valueA,
71  const string& prefixA,
72  const string& nsURIA)
73  : localname(localNameA)
74  , prefix(prefixA)
75  , nsURI(nsURIA)
76  , value(valueA)
77  {
78  }
79 
83  XMLAttribute::XMLAttribute(const xmlChar** chunkOfFivePointers)
84  {
85  fromSAX2NamespaceAttributes(chunkOfFivePointers);
86  }
87 
89  : localname(proto.localname)
90  , prefix(proto.prefix)
91  , nsURI(proto.nsURI)
92  , value(proto.value)
93  {
94  }
95 
98  {
99  if (&rhs == this)
100  {
101  return *this;
102  }
103  localname = rhs.localname;
104  prefix = rhs.prefix;
105  value = rhs.value;
106  nsURI = rhs.nsURI; // jhrg 3/16/11
107  return *this;
108  }
109 
110  void
111  XMLAttribute::fromSAX2NamespaceAttributes(const xmlChar** chunkOfFivePointers)
112  {
113  const xmlChar* xmlLocalName = (*chunkOfFivePointers++);
114  const xmlChar* xmlPrefix = (*chunkOfFivePointers++);
115  const xmlChar* xmlURI = (*chunkOfFivePointers++);
116  const xmlChar* xmlValueStart = (*chunkOfFivePointers++);
117  // pointer to end of the value since not null terminated.
118  const xmlChar* xmlValueEnd = (*chunkOfFivePointers++);
119 
120  // makeString calls map null into "".
121  localname = XMLUtil::xmlCharToString(xmlLocalName);
122  prefix = XMLUtil::xmlCharToString(xmlPrefix);
124  value = XMLUtil::xmlCharToStringFromIterators(xmlValueStart, xmlValueEnd);
125  }
126 
128  string
130  {
131  return getQName(prefix, localname);
132  }
133 
138  string
140  {
141  return getQName() + "=\"" + value + "\"";
142  }
143 
144  /*static */
145  string
146  XMLAttribute::getQName(const string& prefix, const string& localname)
147  {
148  if (prefix.empty())
149  {
150  return localname;
151  }
152  else
153  {
154  return prefix + ":" + localname;
155  }
156  }
157 
160  : _attributes()
161  {
162  }
163 
165  {
166  }
167 
170  {
171  return _attributes.begin();
172  }
173 
176  {
177  return _attributes.end();
178  }
179 
180  bool
182  {
183  return _attributes.empty();
184  }
185 
186  void
188  {
189  // won't resize, we might be reusing it so no point.
190  _attributes.clear();
191  }
192 
193  void
195  {
196  XMLAttributeMap::iterator foundIt = findByQName(attribute.getQName());
197  // if in there, replace it.
198  if (foundIt != _attributes.end())
199  {
200  // replace with a copy of new one
201  (*foundIt) = XMLAttribute(attribute);
202  }
203 
204  // otherwise push on a new one
205  _attributes.push_back(attribute);
206  }
207 
208  const string /*& returns a reference to a local temp object (the else clause). jhrg 4/16/14*/
209  XMLAttributeMap::getValueForLocalNameOrDefault(const string& localname, const string& defVal/*=""*/) const
210  {
211  const XMLAttribute* pAttr = getAttributeByLocalName(localname);
212  if (pAttr)
213  {
214  return pAttr->value;
215  }
216  else
217  {
218  // Reference to a local temporary object. jhrg 4/16/14
219  return defVal;
220  }
221  }
222 
223  const XMLAttribute*
224  XMLAttributeMap::getAttributeByLocalName(const string& localname) const
225  {
226  const XMLAttribute* pAtt = 0; // if not found
227  for (XMLAttributeMap::const_iterator it=begin(); it != end(); ++it)
228  {
229  const XMLAttribute& rAttr = *it;
230  if (rAttr.localname == localname)
231  {
232  pAtt = &rAttr;
233  break;
234  }
235  }
236  return pAtt;
237  }
238 
239  const XMLAttribute*
240  XMLAttributeMap::getAttributeByQName(const string& qname) const
241  {
242  const XMLAttribute* pAtt = 0; // if not found
243  for (XMLAttributeMap::const_iterator it=begin(); it != end(); ++it)
244  {
245  const XMLAttribute& rAttr = *it;
246  if (rAttr.getQName() == qname)
247  {
248  pAtt = &rAttr;
249  break;
250  }
251  }
252  return pAtt;
253  }
254 
255  const XMLAttribute*
256  XMLAttributeMap::getAttributeByQName(const string& prefix, const string& localname) const
257  {
258  return getAttributeByQName( XMLAttribute::getQName(prefix, localname) );
259  }
260 
262  string
264  {
265  string result("");
267  for (it = begin(); it != end(); ++it)
268  {
269  const XMLAttribute& attr = *it;
270  result += (attr.getQName() + "=\"" + attr.value + "\" ");
271  }
272  return result;
273  }
274 
276  XMLAttributeMap::findByQName(const string& qname)
277  {
279  for (it = _attributes.begin();
280  it != _attributes.end();
281  ++it)
282  {
283  if (it->getQName() == qname)
284  {
285  break;
286  }
287  }
288  return it;
289  }
290 
292 
293  XMLNamespace::XMLNamespace(const string& prefixArg/*=""*/, const string& uriArg/*=""*/)
294  : prefix(prefixArg)
295  , uri(uriArg)
296  {
297  }
298 
300  : prefix(proto.prefix)
301  , uri(proto.uri)
302  {
303  }
304 
305  XMLNamespace&
307  {
308  if (this == &rhs)
309  {
310  return *this;
311  }
312 
313  prefix = rhs.prefix;
314  uri = rhs.uri;
315  return *this;
316  }
317 
318  void
319  XMLNamespace::fromSAX2Namespace(const xmlChar** pNamespace)
320  {
321  prefix = XMLUtil::xmlCharToString(*pNamespace);
322  uri = XMLUtil::xmlCharToString(*(pNamespace+1));
323  }
324 
326  string
328  {
329  string attr("xmlns");
330  if (!prefix.empty())
331  {
332  attr += ( string(":") + prefix );
333  }
334  attr += string("=\"");
335  attr += uri;
336  attr += string("\"");
337  return attr;
338  }
339 
341 
343  : _namespaces()
344  {
345  }
346 
348  {
349  _namespaces.clear();
350  }
351 
353  : _namespaces(proto._namespaces)
354  {
355  }
356 
359  {
360  if (this == &rhs)
361  {
362  return *this;
363  }
364  _namespaces = rhs._namespaces;
365  return *this;
366  }
367 
368  void
369  XMLNamespaceMap::fromSAX2Namespaces(const xmlChar** pNamespaces, int numNamespaces)
370  {
371  clear();
372  for (int i=0; i<numNamespaces; ++i)
373  {
374  XMLNamespace ns;
375  ns.fromSAX2Namespace(pNamespaces);
376  pNamespaces += 2; // this array is stride 2
377  addNamespace(ns);
378  }
379  }
380 
381  string
383  {
384  string allAttrs("");
385  for (XMLNamespaceMap::const_iterator it = begin(); it != end(); ++it)
386  {
387  const XMLNamespace& ns = *it;
388  allAttrs += string(" ") + ns.getAsAttributeString();
389  }
390  return allAttrs;
391  }
392 
395  {
396  return _namespaces.begin();
397  }
398 
401  {
402  return _namespaces.end();
403  }
404 
406  XMLNamespaceMap::find(const string& prefix) const
407  {
409  for (foundIt = begin(); foundIt != end(); ++foundIt)
410  {
411  if (foundIt->prefix == prefix)
412  {
413  break;
414  }
415  }
416  return foundIt;
417  }
418 
419  bool
420  XMLNamespaceMap::isInMap(const string& prefix) const
421  {
422  return ( find(prefix) != end() );
423  }
424 
425  void
427  {
428  XMLNamespaceMap::iterator foundIt = findNonConst(ns.prefix);
429  if (foundIt == _namespaces.end()) // not found, push
430  {
431  _namespaces.push_back(ns);
432  }
433  else
434  {
435  // overwrite
436  (*foundIt) = XMLNamespace(ns);
437  }
438  }
439 
440  void
442  {
443  _namespaces.clear();
444  }
445 
446  bool
448  {
449  return _namespaces.empty();
450  }
451 
452 
453  XMLNamespaceMap::iterator
454  XMLNamespaceMap::findNonConst(const string& prefix)
455  {
456  XMLNamespaceMap::iterator foundIt;
457  for (foundIt = _namespaces.begin(); foundIt != _namespaces.end(); ++foundIt)
458  {
459  if (foundIt->prefix == prefix)
460  {
461  break;
462  }
463  }
464  return foundIt;
465  }
466 
468 
470  : _stack()
471  {
472  }
473 
475  {
476  _stack.clear();
477  _stack.resize(0);
478  }
479 
481  : _stack(proto._stack)
482  {
483  }
484 
487  {
488  if (this == &rhs)
489  {
490  return *this;
491  }
492  _stack = rhs._stack;
493  return *this;
494  }
495 
496  void
498  {
499  _stack.push_back(nsMap);
500  }
501 
502  void
504  {
505  _stack.pop_back();
506  }
507 
508  const XMLNamespaceMap&
510  {
511  return _stack.back();
512  }
513 
514  bool
516  {
517  return _stack.empty();
518  }
519 
520  void
522  {
523  _stack.clear();
524  }
525 
528  {
529  return _stack.rbegin();
530  }
531 
534  {
535  return _stack.rend();
536  }
537 
538  void
540  {
541  // Scan the stack in top (lexically innermost) to bottom order, adding in
542  // the namespaces we don't have a prefix for.
543  for (XMLNamespaceStack::const_iterator it = begin(); it != end(); ++it)
544  {
545  addMissingNamespaces(nsFlattened, *it);
546  }
547  }
548 
549  /* static */
550  void
551  XMLNamespaceStack::addMissingNamespaces(XMLNamespaceMap& intoMap, const XMLNamespaceMap& fromMap)
552  {
553  for (XMLNamespaceMap::const_iterator it = fromMap.begin(); it != fromMap.end(); ++it)
554  {
555  const XMLNamespace& ns = *it;
556  // If this namespace is not in the output map, add it
557  if (intoMap.find(ns.prefix) == intoMap.end())
558  {
559  intoMap.addNamespace(ns);
560  }
561  // otherwise, it's been lexically shadowed, so ignore it.
562  }
563  }
564 }; // namespace ncml_module
void fromSAX2Namespace(const xmlChar **namespaces)
Assuming the pointer is an array of two strings: {prefix, uri}.
Definition: XMLHelpers.cc:319
XMLNamespaceMap::const_iterator find(const string &prefix) const
Return the iterator to the element or end() if not found.
Definition: XMLHelpers.cc:406
XMLNamespaceMap::const_iterator end() const
Definition: XMLHelpers.cc:400
vector< XMLNamespaceMap >::const_reverse_iterator const_iterator
Definition: XMLHelpers.h:213
XMLAttributeMap::const_iterator begin() const
Definition: XMLHelpers.cc:169
vector< XMLAttribute >::iterator iterator
Definition: XMLHelpers.h:105
XMLNamespace & operator=(const XMLNamespace &rhs)
Definition: XMLHelpers.cc:306
bool isInMap(const string &prefix) const
Definition: XMLHelpers.cc:420
XMLNamespaceStack & operator=(const XMLNamespaceStack &rhs)
Definition: XMLHelpers.cc:486
An abstract superclass for NCMLArray that handles the non-parameterized functionality and allows u...
const XMLNamespaceMap & top() const
Definition: XMLHelpers.cc:509
static string xmlCharToStringFromIterators(const xmlChar *startPtr, const xmlChar *endPtr)
Definition: XMLHelpers.cc:53
string getAsXMLString() const
Get the standard string version as found in an element: prefix:localname="value" localname="value" if...
Definition: XMLHelpers.cc:139
const string getValueForLocalNameOrDefault(const string &localname, const string &defVal="") const
If there is an attribute with localname, return its value, else return default.
Definition: XMLHelpers.cc:209
const XMLAttribute * getAttributeByLocalName(const string &localname) const
These return null if the attribute was not found.
Definition: XMLHelpers.cc:224
XMLNamespace(const string &prefix="", const string &uri="")
Definition: XMLHelpers.cc:293
void fromSAX2Namespaces(const xmlChar **pNamespaces, int numNamespaces)
Read them all in from the xmlChar array.
Definition: XMLHelpers.cc:369
XMLAttribute & operator=(const XMLAttribute &rhs)
Definition: XMLHelpers.cc:97
XMLNamespaceMap::const_iterator begin() const
Definition: XMLHelpers.cc:394
string getAllNamespacesAsAttributeString() const
Get a big string full of xmlns:prefix="uri" attributes, separated by spaces.
Definition: XMLHelpers.cc:382
void addAttribute(const XMLAttribute &attribute)
TODO how do we tell if this exists? Does it replace? Do we care?
Definition: XMLHelpers.cc:194
void getFlattenedNamespacesUsingLexicalScoping(XMLNamespaceMap &nsFlattened) const
Scanning from the stack top downwards, add the first found new XMLNamespace (in terms of its prefix) ...
Definition: XMLHelpers.cc:539
string getAsAttributeString() const
Get the namespace as attribute string, ie "xmlns:prefix=\"uri"" for serializing.
Definition: XMLHelpers.cc:327
XMLAttribute(const string &localName="", const string &value="", const string &prefix="", const string &nsURI="")
Definition: XMLHelpers.cc:69
static string xmlCharToString(const xmlChar *pChars)
Definition: XMLHelpers.cc:38
XMLAttributeMap::const_iterator end() const
Definition: XMLHelpers.cc:175
XMLNamespaceStack::const_iterator begin() const
Starts from the top (most recently pushed) and iterates to the bottom (first pushed).
Definition: XMLHelpers.cc:527
void clear()
make empty
Definition: XMLHelpers.cc:187
vector< XMLAttribute >::const_iterator const_iterator
Definition: XMLHelpers.h:104
string getAllAttributesAsString() const
The classic {prefix:}foo="value" whitespace separated.
Definition: XMLHelpers.cc:263
const XMLAttribute * getAttributeByQName(const string &qname) const
Definition: XMLHelpers.cc:240
void push(const XMLNamespaceMap &nsMap)
Definition: XMLHelpers.cc:497
void addNamespace(const XMLNamespace &ns)
If the given prefix is already in the map, ns REPLACES it.
Definition: XMLHelpers.cc:426
XMLNamespaceStack::const_iterator end() const
Definition: XMLHelpers.cc:533
string getQName() const
get the name with the prefix:localname if prefix not empty else localname
Definition: XMLHelpers.cc:129
XMLNamespaceMap & operator=(const XMLNamespaceMap &rhs)
Definition: XMLHelpers.cc:358
vector< XMLNamespace >::const_iterator const_iterator
Definition: XMLHelpers.h:171
void fromSAX2NamespaceAttributes(const xmlChar **chunkOfFivePointers)
Fill in the fields from the SAX2 namespace attributes array.
Definition: XMLHelpers.cc:111