libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
DDXParserSAX2.h
Go to the documentation of this file.
1
2// -*- mode: c++; c-basic-offset:4 -*-
3
4// This file is part of libdap, A C++ implementation of the OPeNDAP Data
5// Access Protocol.
6
7// Copyright (c) 2003 OPeNDAP, Inc.
8// Author: James Gallagher <jgallagher@opendap.org>
9//
10// This library is free software; you can redistribute it and/or
11// modify it under the terms of the GNU Lesser General Public
12// License as published by the Free Software Foundation; either
13// version 2.1 of the License, or (at your option) any later version.
14//
15// This library is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18// Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public
21// License along with this library; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23//
24// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25
26#ifndef ddx_parser_h
27#define ddx_parser_h
28
29#include <map>
30#include <stack>
31#include <string.h>
32#include <string>
33
34#include <libxml/parserInternals.h>
35
36#ifndef ddx_exceptions_h
37#include "DDXExceptions.h"
38#endif
39
40#ifndef _dds_h
41#include "DDS.h"
42#endif
43
44#ifndef _basetype_h
45#include "BaseType.h"
46#endif
47
48#ifndef base_type_factory_h
49#include "BaseTypeFactory.h"
50#endif
51
52namespace libdap {
53
79class DDXParser {
80private:
83 enum ParseState {
84 parser_start,
85
86 inside_dataset,
87
88 inside_attribute_container,
89 inside_attribute,
90 inside_attribute_value,
91 inside_other_xml_attribute,
92
93 inside_alias,
94
95 // This covers Byte, ..., Url.
96 inside_simple_type,
97
98 inside_array,
99 inside_dimension,
100
101 inside_grid,
102 inside_map,
103
104 inside_structure,
105 inside_sequence,
106
107 inside_blob_href,
108
109 parser_unknown,
110 parser_error
111 };
112
113 xmlSAXHandler ddx_sax_parser;
114
115 BaseTypeFactory *d_factory;
116
117 // These stacks hold the state of the parse as it progresses.
118 stack<ParseState> s; // Current parse state
119 stack<BaseType *> bt_stack; // current variable(s)
120 stack<AttrTable *> at_stack; // current attribute table
121
122 // Accumulate stuff inside an 'OtherXML' DAP attribute here
123 string other_xml;
124
125 // When we're parsing unknown XML, how deeply is it nested? This is used
126 // for the OtherXML DAP attributes.
127 unsigned int other_xml_depth;
128 unsigned int unknown_depth;
129
130 // These are used for processing errors.
131 string error_msg; // Error message(s), if any.
132 xmlParserCtxtPtr ctxt; // used for error message line numbers
133
134 // The results of the parse operation are stored in these fields.
135 DDS *dds; // dump DDX here
136 string *blob_href; // put href to blob here
137
138 // These hold temporary values read during the parse.
139 string dods_attr_name; // DAP2 attributes, not XML attributes
140 string dods_attr_type; // ... not XML ...
141 string char_data; // char data in value elements; null after use
142 string root_ns; // What is the namespace of the root node (Dataset)
143
144 class XMLAttribute {
145 public:
146 string prefix;
147 string nsURI;
148 string value;
149
150 void clone(const XMLAttribute &src) {
151 prefix = src.prefix;
152 nsURI = src.nsURI;
153 value = src.value;
154 }
155
156 XMLAttribute() : prefix(""), nsURI(""), value("") {}
157 XMLAttribute(const string &p, const string &ns, const string &v) : prefix(p), nsURI(ns), value(v) {}
158 // 'attributes' as passed from libxml2 is a five element array but this
159 // ctor gets the back four elements.
160 XMLAttribute(const xmlChar **attributes /*[4]*/) {
161 prefix = attributes[0] != 0 ? (const char *)attributes[0] : "";
162 nsURI = attributes[1] != 0 ? (const char *)attributes[1] : "";
163 value = string((const char *)attributes[2], (const char *)attributes[3]);
164 }
165 XMLAttribute(const XMLAttribute &rhs) { clone(rhs); }
166 ~XMLAttribute() {}
167 XMLAttribute &operator=(const XMLAttribute &rhs) {
168 if (this == &rhs)
169 return *this;
170 clone(rhs);
171 return *this;
172 }
173 };
174
175 typedef map<string, XMLAttribute> XMLAttrMap;
176 XMLAttrMap attribute_table; // dump XML attributes here
177
178 XMLAttrMap::iterator attr_table_begin() { return attribute_table.begin(); }
179
180 XMLAttrMap::iterator attr_table_end() { return attribute_table.end(); }
181
182 map<string, string> namespace_table;
183
184 // These are kind of silly...
185 void set_state(DDXParser::ParseState state);
186 DDXParser::ParseState get_state() const;
187 void pop_state();
188
189 // Glue for the BaseTypeFactory class.
190 BaseType *factory(Type t, const string &name);
191
192 // Common cleanup code for intern() and intern_stream()
193#if 0
194 //void cleanup_parse(xmlParserCtxtPtr &context);
195#endif
196 void cleanup_parse();
197
204 void transfer_xml_attrs(const xmlChar **attrs, int nb_attributes);
205 void transfer_xml_ns(const xmlChar **namespaces, int nb_namespaces);
206 bool check_required_attribute(const string &attr);
207 bool check_attribute(const string &attr);
208
209 void process_attribute_element(const xmlChar **attrs, int nb_attrs);
210 void process_attribute_alias(const xmlChar **attrs, int nb_attrs);
211
212 void process_variable(Type t, ParseState s, const xmlChar **attrs, int nb_attributes);
213
214 void process_dimension(const xmlChar **attrs, int nb_attrs);
215 void process_blob(const xmlChar **attrs, int nb_attrs);
216
217 bool is_attribute_or_alias(const char *name, const xmlChar **attrs, int nb_attributes);
218 bool is_variable(const char *name, const xmlChar **attrs, int nb_attributes);
219
220 void finish_variable(const char *tag, Type t, const char *expected);
222
224 DDXParser();
225
226 friend class DDXParserTest;
227
228public:
230 : d_factory(factory), other_xml(""), other_xml_depth(0), unknown_depth(0), error_msg(""), ctxt(0), dds(0),
231 blob_href(0), dods_attr_name(""), dods_attr_type(""), char_data(""), root_ns("") {
232 memset(&ddx_sax_parser, 0, sizeof(xmlSAXHandler));
233
234 ddx_sax_parser.getEntity = &DDXParser::ddx_get_entity;
235 ddx_sax_parser.startDocument = &DDXParser::ddx_start_document;
236 ddx_sax_parser.endDocument = &DDXParser::ddx_end_document;
237 ddx_sax_parser.characters = &DDXParser::ddx_get_characters;
238 ddx_sax_parser.ignorableWhitespace = &DDXParser::ddx_ignoreable_whitespace;
239 ddx_sax_parser.cdataBlock = &DDXParser::ddx_get_cdata;
240 ddx_sax_parser.warning = &DDXParser::ddx_fatal_error;
241 ddx_sax_parser.error = &DDXParser::ddx_fatal_error;
242 ddx_sax_parser.fatalError = &DDXParser::ddx_fatal_error;
243 ddx_sax_parser.initialized = XML_SAX2_MAGIC;
244 ddx_sax_parser.startElementNs = &DDXParser::ddx_sax2_start_element;
245 ddx_sax_parser.endElementNs = &DDXParser::ddx_sax2_end_element;
246 }
247 void intern(const string &document, DDS *dest_dds, string &cid);
248 void intern_stream(FILE *in, DDS *dds, string &cid, const string &boundary = "");
249 void intern_stream(istream &in, DDS *dds, string &cid, const string &boundary = "");
250
251 static void ddx_start_document(void *parser);
252 static void ddx_end_document(void *parser);
253
254 static void ddx_sax2_start_element(void *parser, const xmlChar *localname, const xmlChar *prefix,
255 const xmlChar *URI, int nb_namespaces, const xmlChar **namespaces,
256 int nb_attributes, int nb_defaulted, const xmlChar **attributes);
257 static void ddx_sax2_end_element(void *parser, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI);
258
259 static void ddx_get_characters(void *parser, const xmlChar *ch, int len);
260 static void ddx_ignoreable_whitespace(void *parser, const xmlChar *ch, int len);
261 static void ddx_get_cdata(void *parser, const xmlChar *value, int len);
262
263 static xmlEntityPtr ddx_get_entity(void *parser, const xmlChar *name);
264 static void ddx_fatal_error(void *parser, const char *msg, ...);
265};
266
267} // namespace libdap
268
269#endif // ddx_parser_h
The basic data type for the DODS DAP types.
Definition BaseType.h:118
static void ddx_fatal_error(void *parser, const char *msg,...)
static void ddx_ignoreable_whitespace(void *parser, const xmlChar *ch, int len)
static void ddx_get_characters(void *parser, const xmlChar *ch, int len)
static void ddx_sax2_start_element(void *parser, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes)
static void ddx_start_document(void *parser)
void intern_stream(FILE *in, DDS *dds, string &cid, const string &boundary="")
Read the DDX from a stream instead of a file.
friend class DDXParserTest
static void ddx_sax2_end_element(void *parser, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI)
void intern(const string &document, DDS *dest_dds, string &cid)
DDXParser(BaseTypeFactory *factory)
static void ddx_end_document(void *parser)
static void ddx_get_cdata(void *parser, const xmlChar *value, int len)
static xmlEntityPtr ddx_get_entity(void *parser, const xmlChar *name)
top level DAP object to house generic methods
Definition AISConnect.cc:30
Type
Identifies the data type.
Definition Type.h:94