36#include <libxml2/libxml/parserInternals.h>
43#include "D4Attributes.h"
46#include "D4BaseTypeFactory.h"
48#include "DapXmlNamespaces.h"
49#include "D4ParserSax2.h"
56static const char *states[] = {
65 "inside_attribute_container",
67 "inside_attribute_value",
68 "inside_other_xml_attribute",
93static bool is_not(
const char *name,
const char *tag)
95 return strcmp(name, tag) != 0;
107D4ParserSax2::enum_def()
109 if (!d_enum_def) d_enum_def =
new D4EnumDef;
121D4ParserSax2::dim_def() {
122 if (!d_dim_def) d_dim_def =
new D4Dimension;
132void D4ParserSax2::transfer_xml_attrs(
const xmlChar **attributes,
int nb_attributes)
134 if (!xml_attrs.empty())
139 unsigned int index = 0;
140 for (
int i = 0; i < nb_attributes; ++i, index += 5) {
141 xml_attrs.insert(map<string, XMLAttribute>::value_type(
string((
const char *)attributes[index]),
142 XMLAttribute(attributes + index + 1)));
144 DBG(cerr <<
"XML Attribute '" << (
const char *)attributes[index] <<
"': "
145 << xml_attrs[(
const char *)attributes[index]].value << endl);
155void D4ParserSax2::transfer_xml_ns(
const xmlChar **namespaces,
int nb_namespaces)
158 for (
int i = 0; i < nb_namespaces; ++i) {
159 namespace_table.insert(map<string, string>::value_type(namespaces[i * 2] != 0 ? (
const char *)namespaces[i * 2] :
"",
160 (const char *)namespaces[i * 2 + 1]));
170bool D4ParserSax2::check_required_attribute(
const string & attr)
172 if (xml_attrs.find(attr) == xml_attrs.end()) {
173 dmr_error(
this,
"Required attribute '%s' not found.", attr.c_str());
186bool D4ParserSax2::check_attribute(
const string & attr)
188 return (xml_attrs.find(attr) != xml_attrs.end());
191bool D4ParserSax2::process_dimension_def(
const char *name,
const xmlChar **attrs,
int nb_attributes)
193 if (is_not(name,
"Dimension"))
196 transfer_xml_attrs(attrs, nb_attributes);
198 if (!(check_required_attribute(
"name") && check_required_attribute(
"size"))) {
199 dmr_error(
this,
"The required attribute 'name' or 'size' was missing from a Dimension element.");
204 dim_def()->set_name(xml_attrs[
"name"].value);
206 dim_def()->set_size(xml_attrs[
"size"].value);
209 dmr_error(
this,
"%s", e.get_error_message().c_str());
233bool D4ParserSax2::process_dimension(
const char *name,
const xmlChar **attrs,
int nb_attributes)
235 if (is_not(name,
"Dim"))
238 transfer_xml_attrs(attrs, nb_attributes);
240 if (check_attribute(
"size") && check_attribute(
"name")) {
241 dmr_error(
this,
"Only one of 'size' and 'name' are allowed in a Dim element, but both were used.");
244 if (!(check_attribute(
"size") || check_attribute(
"name"))) {
245 dmr_error(
this,
"Either 'size' or 'name' must be used in a Dim element.");
251 BaseType *b = top_basetype();
254 Array *a =
static_cast<Array*
>(dmr()->
factory()->
NewVariable(dods_array_c, b->name()));
255 a->set_is_dap4(
true);
256 a->add_var_nocopy(b);
257 a->set_attributes_nocopy(b->attributes());
261 b->set_attributes_nocopy(0);
268 Array *a =
static_cast<Array*
>(top_basetype());
269 if (check_attribute(
"size")) {
271 a->append_dim_ll(strtoll(xml_attrs[
"size"].value.c_str(),
nullptr,10));
273 a->append_dim(atoi(xml_attrs[
"size"].value.c_str()));
277 else if (check_attribute(
"name")) {
278 string name = xml_attrs[
"name"].value;
280 D4Dimension *dim = 0;
287 throw Error(
"The dimension '" + name +
"' was not found while parsing the variable '" + a->name() +
"'.");
295bool D4ParserSax2::process_map(
const char *name,
const xmlChar **attrs,
int nb_attributes)
297 if (is_not(name,
"Map"))
300 transfer_xml_attrs(attrs, nb_attributes);
302 if (!check_attribute(
"name")) {
303 dmr_error(
this,
"The 'name' attribute must be used in a Map element.");
309 BaseType *b = top_basetype();
312 Array *a =
static_cast<Array*
>(dmr()->
factory()->
NewVariable(dods_array_c, b->name()));
313 a->set_is_dap4(
true);
314 a->add_var_nocopy(b);
315 a->set_attributes_nocopy(b->attributes());
319 b->set_attributes_nocopy(0);
326 Array *a =
static_cast<Array*
>(top_basetype());
328 string map_name = xml_attrs[
"name"].value;
329 if (xml_attrs[
"name"].value[0] !=
'/')
330 map_name = top_group()->
FQN() + map_name;
332 Array *map_source = 0;
334 if (map_name[0] ==
'/')
345 if (!map_source && d_strict)
346 throw Error(
"The Map '" + map_name +
"' was not found while parsing the variable '" + a->name() +
"'.");
348 a->maps()->add_map(
new D4Map(map_name, map_source));
353bool D4ParserSax2::process_group(
const char *name,
const xmlChar **attrs,
int nb_attributes)
355 if (is_not(name,
"Group"))
358 transfer_xml_attrs(attrs, nb_attributes);
360 if (!check_required_attribute(
"name")) {
361 dmr_error(
this,
"The required attribute 'name' was missing from a Group element.");
367 dmr_fatal_error(
this,
"Could not instantiate the Group '%s'.", xml_attrs[
"name"].value.c_str());
371 D4Group *grp =
static_cast<D4Group*
>(btp);
375 grp->set_is_dap4(
true);
378 D4Group *parent = top_group();
384 grp->set_parent(parent);
385 parent->add_group_nocopy(grp);
388 push_attributes(grp->attributes());
398inline bool D4ParserSax2::process_attribute(
const char *name,
const xmlChar **attrs,
int nb_attributes)
400 if (is_not(name,
"Attribute"))
404 transfer_xml_attrs(attrs, nb_attributes);
407 if (!(check_required_attribute(
string(
"name")) && check_required_attribute(
string(
"type")))) {
408 dmr_error(
this,
"The required attribute 'name' or 'type' was missing from an Attribute element.");
412 if (xml_attrs[
"type"].value ==
"Container") {
413 push_state(inside_attribute_container);
415 DBG(cerr <<
"Pushing attribute container " << xml_attrs[
"name"].value << endl);
416 D4Attribute *child =
new D4Attribute(xml_attrs[
"name"].value, attr_container_c);
418 D4Attributes *tos = top_attributes();
422 dmr_fatal_error(
this,
"Expected an Attribute container on the top of the attribute stack.");
426 tos->add_attribute_nocopy(child);
427 push_attributes(child->attributes());
429 else if (xml_attrs[
"type"].value ==
"OtherXML") {
430 push_state(inside_other_xml_attribute);
432 dods_attr_name = xml_attrs[
"name"].value;
433 dods_attr_type = xml_attrs[
"type"].value;
436 push_state(inside_attribute);
438 dods_attr_name = xml_attrs[
"name"].value;
439 dods_attr_type = xml_attrs[
"type"].value;
450inline bool D4ParserSax2::process_enum_def(
const char *name,
const xmlChar **attrs,
int nb_attributes)
452 if (is_not(name,
"Enumeration"))
455 transfer_xml_attrs(attrs, nb_attributes);
457 if (!(check_required_attribute(
"name") && check_required_attribute(
"basetype"))) {
458 dmr_error(
this,
"The required attribute 'name' or 'basetype' was missing from an Enumeration element.");
464 dmr_error(
this,
"The Enumeration '%s' must have an integer type, instead the type '%s' was used.",
465 xml_attrs[
"name"].value.c_str(), xml_attrs[
"basetype"].value.c_str());
470 string enum_def_path = xml_attrs[
"name"].value;
473 if (xml_attrs[
"name"].value[0] !=
'/')
474 enum_def_path = top_group()->
FQN() + enum_def_path;
476 enum_def()->set_name(enum_def_path);
477 enum_def()->set_type(t);
482inline bool D4ParserSax2::process_enum_const(
const char *name,
const xmlChar **attrs,
int nb_attributes)
484 if (is_not(name,
"EnumConst"))
488 transfer_xml_attrs(attrs, nb_attributes);
490 if (!(check_required_attribute(
"name") && check_required_attribute(
"value"))) {
491 dmr_error(
this,
"The required attribute 'name' or 'value' was missing from an EnumConst element.");
495 istringstream iss(xml_attrs[
"value"].value);
497 iss >> skipws >> value;
498 if (iss.fail() || iss.bad()) {
499 dmr_error(
this,
"Expected an integer value for an Enumeration constant, got '%s' instead.",
500 xml_attrs[
"value"].value.c_str());
502 else if (!enum_def()->is_valid_enum_value(value)) {
503 dmr_error(
this,
"In an Enumeration constant, the value '%s' cannot fit in a variable of type '%s'.",
504 xml_attrs[
"value"].value.c_str(),
D4type_name(d_enum_def->type()).c_str());
508 enum_def()->add_value(xml_attrs[
"name"].value, value);
519inline bool D4ParserSax2::process_variable(
const char *name,
const xmlChar **attrs,
int nb_attributes)
523 process_variable_helper(t, inside_simple_type, attrs, nb_attributes);
528 case dods_structure_c:
529 process_variable_helper(t, inside_constructor, attrs, nb_attributes);
532 case dods_sequence_c:
533 process_variable_helper(t, inside_constructor, attrs, nb_attributes);
549void D4ParserSax2::process_variable_helper(
Type t, ParseState s,
const xmlChar **attrs,
int nb_attributes)
551 transfer_xml_attrs(attrs, nb_attributes);
553 if (check_required_attribute(
"name")) {
556 dmr_fatal_error(
this,
"Could not instantiate the variable '%s'.", xml_attrs[
"name"].value.c_str());
560 if ((t == dods_enum_c) && check_required_attribute(
"enum")) {
561 D4EnumDef *enum_def = 0;
562 string enum_path = xml_attrs[
"enum"].value;
563 if (enum_path[0] ==
'/')
564 enum_def = dmr()->
root()->find_enum_def(enum_path);
566 enum_def = top_group()->find_enum_def(enum_path);
569 dmr_fatal_error(
this,
"Could not find the Enumeration definition '%s'.", enum_path.c_str());
571 static_cast<D4Enum*
>(btp)->set_enumeration(enum_def);
574 btp->set_is_dap4(
true);
577 push_attributes(btp->attributes());
597 parser->d_error_msg =
"";
598 parser->char_data =
"";
607 if (parser->debug()) cerr <<
"Parser start state: " << states[parser->get_state()] << endl;
616 if (parser->debug()) cerr <<
"Parser end state: " << states[parser->get_state()] << endl;
618 if (parser->get_state() != parser_end)
619 D4ParserSax2::dmr_error(parser,
"The document contained unbalanced tags.");
623 if (parser->get_state() == parser_error || parser->get_state() == parser_fatal_error)
626 if (!parser->empty_basetype() || parser->empty_group())
627 D4ParserSax2::dmr_error(parser,
"The document did not contain a valid root Group or contained unbalanced tags.");
630 parser->pop_attributes();
647 int nb_namespaces,
const xmlChar **namespaces,
int nb_attributes,
int ,
648 const xmlChar **attributes)
651 const char *localname = (
const char *) l;
653 if (parser->debug()) cerr <<
"Start element " << localname <<
" prefix: "<< (prefix?(
char *)prefix:
"null") <<
" ns: "<< (URI?(
char *)URI:
"null")
654 <<
" (state: " << states[parser->get_state()] <<
")" << endl;
656 if(parser->get_state() != parser_error){
658 if (parser->debug()) cerr <<
"dap4_ns_name: " << dap4_ns_name << endl;
660 string this_element_ns_name = (URI != 0) ? ((
char *)URI) :
"";
661 if (parser->debug()) cerr <<
"this_element_ns_name: " << this_element_ns_name << endl;
663 if(this_element_ns_name.compare(dap4_ns_name)){
664 if (parser->debug()) cerr <<
"Start of non DAP4 element: " << localname <<
" detected." << endl;
665 parser->push_state(not_dap4_element);
671 switch (parser->get_state()) {
673 if (is_not(localname,
"Dataset"))
674 D4ParserSax2::dmr_error(parser,
"Expected DMR to start with a Dataset element; found '%s' instead.", localname);
676 parser->root_ns = URI ? (
const char *) URI :
"";
677 parser->transfer_xml_attrs(attributes, nb_attributes);
679 if (parser->check_required_attribute(
string(
"name")))
680 parser->dmr()->set_name(parser->xml_attrs[
"name"].value);
682 if (parser->check_attribute(
"dapVersion"))
685 if (parser->check_attribute(
"dmrVersion"))
686 parser->dmr()->set_dmr_version(parser->xml_attrs[
"dmrVersion"].value);
688 if (parser->check_attribute(
"base"))
691 if (!parser->root_ns.empty())
695 parser->push_group(parser->dmr()->
root());
697 parser->push_state(inside_dataset);
706 if (parser->process_enum_def(localname, attributes, nb_attributes))
707 parser->push_state(inside_enum_def);
708 else if (parser->process_dimension_def(localname, attributes, nb_attributes))
709 parser->push_state(inside_dim_def);
710 else if (parser->process_group(localname, attributes, nb_attributes))
711 parser->push_state(inside_group);
712 else if (parser->process_variable(localname, attributes, nb_attributes))
716 else if (parser->process_attribute(localname, attributes, nb_attributes))
721 D4ParserSax2::dmr_error(parser,
"Expected an Attribute, Enumeration, Dimension, Group or variable element; found '%s' instead.", localname);
724 case inside_attribute_container:
725 if (parser->process_attribute(localname, attributes, nb_attributes))
728 D4ParserSax2::dmr_error(parser,
"Expected an Attribute element; found '%s' instead.", localname);
731 case inside_attribute:
732 if (parser->process_attribute(localname, attributes, nb_attributes))
734 else if (strcmp(localname,
"Value") == 0)
735 parser->push_state(inside_attribute_value);
737 dmr_error(parser,
"Expected an 'Attribute' or 'Value' element; found '%s' instead.", localname);
740 case inside_attribute_value:
744 case inside_other_xml_attribute:
745 parser->other_xml_depth++;
748 parser->other_xml.append(
"<");
750 parser->other_xml.append((
const char *) prefix);
751 parser->other_xml.append(
":");
753 parser->other_xml.append(localname);
755 if (nb_namespaces != 0) {
756 parser->transfer_xml_ns(namespaces, nb_namespaces);
758 for (map<string, string>::iterator i = parser->namespace_table.begin();
759 i != parser->namespace_table.end(); ++i) {
760 parser->other_xml.append(
" xmlns");
761 if (!i->first.empty()) {
762 parser->other_xml.append(
":");
763 parser->other_xml.append(i->first);
765 parser->other_xml.append(
"=\"");
766 parser->other_xml.append(i->second);
767 parser->other_xml.append(
"\"");
771 if (nb_attributes != 0) {
772 parser->transfer_xml_attrs(attributes, nb_attributes);
773 for (XMLAttrMap::iterator i = parser->xml_attr_begin(); i != parser->xml_attr_end(); ++i) {
774 parser->other_xml.append(
" ");
775 if (!i->second.prefix.empty()) {
776 parser->other_xml.append(i->second.prefix);
777 parser->other_xml.append(
":");
779 parser->other_xml.append(i->first);
780 parser->other_xml.append(
"=\"");
781 parser->other_xml.append(i->second.value);
782 parser->other_xml.append(
"\"");
786 parser->other_xml.append(
">");
789 case inside_enum_def:
791 if (parser->process_enum_const(localname, attributes, nb_attributes))
792 parser->push_state(inside_enum_const);
794 dmr_error(parser,
"Expected an 'EnumConst' element; found '%s' instead.", localname);
797 case inside_enum_const:
805 case inside_dimension:
817 case inside_simple_type:
818 if (parser->process_attribute(localname, attributes, nb_attributes))
820 else if (parser->process_dimension(localname, attributes, nb_attributes))
821 parser->push_state(inside_dim);
822 else if (parser->process_map(localname, attributes, nb_attributes))
823 parser->push_state(inside_map);
825 dmr_error(parser,
"Expected an 'Attribute', 'Dim' or 'Map' element; found '%s' instead.", localname);
828 case inside_constructor:
829 if (parser->process_variable(localname, attributes, nb_attributes))
833 else if (parser->process_attribute(localname, attributes, nb_attributes))
835 else if (parser->process_dimension(localname, attributes, nb_attributes))
836 parser->push_state(inside_dim);
837 else if (parser->process_map(localname, attributes, nb_attributes))
838 parser->push_state(inside_map);
840 D4ParserSax2::dmr_error(parser,
"Expected an Attribute, Dim, Map or variable element; found '%s' instead.", localname);
843 case not_dap4_element:
844 if (parser->debug()) cerr <<
"Inside non DAP4 element. localname: " << localname << endl;
850 parser->push_state(parser_unknown);
854 case parser_fatal_error:
862 if (parser->debug()) cerr <<
"Start element exit state: " << states[parser->get_state()] << endl;
865void D4ParserSax2::dmr_end_element(
void *p,
const xmlChar *l,
const xmlChar *prefix,
const xmlChar *URI)
868 const char *localname = (
const char *) l;
871 cerr <<
"End element " << localname <<
" (state " << states[parser->get_state()] <<
")" << endl;
873 switch (parser->get_state()) {
875 dmr_fatal_error(parser,
"Unexpected state, inside start state while processing element '%s'.", localname);
879 if (is_not(localname,
"Dataset"))
880 D4ParserSax2::dmr_error(parser,
"Expected an end Dataset tag; found '%s' instead.", localname);
883 if (parser->get_state() != parser_start)
887 parser->push_state(parser_end);
892 if (is_not(localname,
"Group"))
893 D4ParserSax2::dmr_error(parser,
"Expected an end tag for a Group; found '%s' instead.", localname);
895 if (!parser->empty_basetype() || parser->empty_group())
896 D4ParserSax2::dmr_error(parser,
897 "The document did not contain a valid root Group or contained unbalanced tags.");
904 case inside_attribute_container:
905 if (is_not(localname,
"Attribute"))
906 D4ParserSax2::dmr_error(parser,
"Expected an end Attribute tag; found '%s' instead.", localname);
909 parser->pop_attributes();
912 case inside_attribute:
913 if (is_not(localname,
"Attribute"))
914 D4ParserSax2::dmr_error(parser,
"Expected an end Attribute tag; found '%s' instead.", localname);
919 case inside_attribute_value: {
920 if (is_not(localname,
"Value"))
921 D4ParserSax2::dmr_error(parser,
"Expected an end value tag; found '%s' instead.", localname);
928 D4Attributes *attrs = parser->top_attributes();
929 D4Attribute *attr = attrs->
get(parser->dods_attr_name);
931 attr =
new D4Attribute(parser->dods_attr_name, StringToD4AttributeType(parser->dods_attr_type));
932 attrs->add_attribute_nocopy(attr);
934 attr->add_value(parser->char_data);
936 parser->char_data =
"";
940 case inside_other_xml_attribute: {
941 if (strcmp(localname,
"Attribute") == 0 && parser->root_ns == (
const char *) URI) {
947 D4Attributes *attrs = parser->top_attributes();
948 D4Attribute *attr = attrs->
get(parser->dods_attr_name);
950 attr =
new D4Attribute(parser->dods_attr_name, StringToD4AttributeType(parser->dods_attr_type));
951 attrs->add_attribute_nocopy(attr);
953 attr->add_value(parser->other_xml);
955 parser->other_xml =
"";
958 if (parser->other_xml_depth == 0) {
959 D4ParserSax2::dmr_error(parser,
"Expected an OtherXML attribute to end! Instead I found '%s'",
963 parser->other_xml_depth--;
965 parser->other_xml.append(
"</");
967 parser->other_xml.append((
const char *) prefix);
968 parser->other_xml.append(
":");
970 parser->other_xml.append(localname);
971 parser->other_xml.append(
">");
976 case inside_enum_def:
977 if (is_not(localname,
"Enumeration"))
978 D4ParserSax2::dmr_error(parser,
"Expected an end Enumeration tag; found '%s' instead.", localname);
979 if (!parser->top_group())
981 "Expected a Group to be the current item, while finishing up an Enumeration.");
984 parser->top_group()->
enum_defs()->add_enum_nocopy(parser->enum_def());
987 parser->clear_enum_def();
992 case inside_enum_const:
993 if (is_not(localname,
"EnumConst"))
994 D4ParserSax2::dmr_error(parser,
"Expected an end EnumConst tag; found '%s' instead.", localname);
999 case inside_dim_def: {
1000 if (is_not(localname,
"Dimension"))
1001 D4ParserSax2::dmr_error(parser,
"Expected an end Dimension tag; found '%s' instead.", localname);
1003 if (!parser->top_group())
1004 D4ParserSax2::dmr_error(parser,
1005 "Expected a Group to be the current item, while finishing up an Dimension.");
1016 parser->clear_dim_def();
1017 parser->pop_state();
1021 case inside_simple_type:
1023 BaseType *btp = parser->top_basetype();
1024 parser->pop_basetype();
1025 parser->pop_attributes();
1027 BaseType *parent = 0;
1028 if (!parser->empty_basetype())
1029 parent = parser->top_basetype();
1030 else if (!parser->empty_group())
1031 parent = parser->top_group();
1033 dmr_fatal_error(parser,
"Both the Variable and Groups stacks are empty while closing a %s element.",
1036 parser->pop_state();
1040 if (parent->type() == dods_array_c)
1041 static_cast<Array*
>(parent)->prototype()->add_var_nocopy(btp);
1043 parent->add_var_nocopy(btp);
1046 D4ParserSax2::dmr_error(parser,
"Expected an end tag for a simple type; found '%s' instead.", localname);
1048 parser->pop_state();
1052 if (is_not(localname,
"Dim"))
1055 parser->pop_state();
1059 if (is_not(localname,
"Map"))
1062 parser->pop_state();
1065 case inside_constructor: {
1066 if (strcmp(localname,
"Structure") != 0 && strcmp(localname,
"Sequence") != 0) {
1067 D4ParserSax2::dmr_error(parser,
"Expected an end tag for a constructor; found '%s' instead.", localname);
1071 BaseType *btp = parser->top_basetype();
1072 parser->pop_basetype();
1073 parser->pop_attributes();
1075 BaseType *parent = 0;
1076 if (!parser->empty_basetype())
1077 parent = parser->top_basetype();
1078 else if (!parser->empty_group())
1079 parent = parser->top_group();
1081 dmr_fatal_error(parser,
"Both the Variable and Groups stacks are empty while closing a %s element.",
1084 parser->pop_state();
1090 parent->add_var_nocopy(btp);
1091 parser->pop_state();
1095 case not_dap4_element:
1096 if (parser->debug()) cerr <<
"End of non DAP4 element: " << localname << endl;
1097 parser->pop_state();
1100 case parser_unknown:
1101 parser->pop_state();
1105 case parser_fatal_error:
1113 if (parser->debug()) cerr <<
"End element exit state: " << states[parser->get_state()] << endl;
1123 switch (parser->get_state()) {
1124 case inside_attribute_value:
1125 parser->char_data.append((
const char *) (ch), len);
1126 DBG(cerr <<
"Characters: '" << parser->char_data <<
"'" << endl);
1129 case inside_other_xml_attribute:
1130 parser->other_xml.append((
const char *) (ch), len);
1131 DBG(cerr <<
"Other XML Characters: '" << parser->other_xml <<
"'" << endl);
1147 switch (parser->get_state()) {
1148 case inside_other_xml_attribute:
1149 parser->other_xml.append((
const char *) (ch), len);
1166 switch (parser->get_state()) {
1167 case inside_other_xml_attribute:
1168 parser->other_xml.append((
const char *) (value), len);
1171 case parser_unknown:
1175 D4ParserSax2::dmr_error(parser,
"Found a CData block but none are allowed by DAP4.");
1187 return xmlGetPredefinedEntity(name);
1205 parser->push_state(parser_fatal_error);
1207 va_start(args, msg);
1209 vsnprintf(str, 1024, msg, args);
1212 int line = xmlSAX2GetLineNumber(parser->d_context);
1214 if (!parser->d_error_msg.empty()) parser->d_error_msg +=
"\n";
1215 parser->d_error_msg +=
"At line " + long_to_string(line) +
": " + string(str);
1218void D4ParserSax2::dmr_error(
void *p,
const char *msg, ...)
1223 parser->push_state(parser_error);
1225 va_start(args, msg);
1227 vsnprintf(str, 1024, msg, args);
1230 int line = xmlSAX2GetLineNumber(parser->d_context);
1232 if (!parser->d_error_msg.empty()) parser->d_error_msg +=
"\n";
1233 parser->d_error_msg +=
"At line " + long_to_string(line) +
": " + string(str);
1240void D4ParserSax2::cleanup_parse()
1242 bool wellFormed = d_context->wellFormed;
1243 bool valid = d_context->valid;
1246 xmlFreeParserCtxt(d_context);
1256 while (!btp_stack.empty()) {
1257 delete top_basetype();
1262 throw Error(
"The DMR was not well formed. " + d_error_msg);
1264 throw Error(
"The DMR was not valid." + d_error_msg);
1265 else if (get_state() == parser_error)
1266 throw Error(d_error_msg);
1267 else if (get_state() == parser_fatal_error)
1268 throw InternalErr(d_error_msg);
1292 throw Error(
"Input stream not open or read error");
1294 throw InternalErr(__FILE__, __LINE__,
"DMR object is null");
1303 if (line.length() == 0)
throw Error(
"No input found while parsing the DMR.");
1305 if (debug) cerr <<
"line: (" << line_num <<
"): " << endl << line << endl << endl;
1307 d_context = xmlCreatePushParserCtxt(&d_dmr_sax_parser,
this, line.c_str(), line.length(),
"stream");
1308 d_context->validate =
true;
1309 push_state(parser_start);
1315 if (debug) cerr <<
"line: (" << line_num <<
"): " << endl << line << endl << endl;
1317 while (!f.eof() && (get_state() != parser_end)) {
1318 xmlParseChunk(d_context, line.c_str(), line.length(), 0);
1324 if (debug) cerr <<
"line: (" << line_num <<
"): " << endl << line << endl << endl;
1327 xmlParseChunk(d_context, line.c_str(), 0, 1);
1335 if (line.length() == 0)
throw Error(
"No input found while parsing the DMR.");
1337 if (debug) cerr <<
"line: (" << line_num <<
"): " << endl << line << endl << endl;
1339 d_context = xmlCreatePushParserCtxt(&d_dmr_sax_parser,
this, line.c_str(), line.length(),
"stream");
1340 d_context->validate =
true;
1341 push_state(parser_start);
1344 long chunk_count = 0;
1345 long chunk_size = 0;
1347 f.read(d_parse_buffer, D4_PARSE_BUFF_SIZE);
1348 chunk_size=f.gcount();
1349 d_parse_buffer[chunk_size]=0;
1350 if (debug) cerr <<
"chunk: (" << chunk_count++ <<
"): " << endl << d_parse_buffer << endl << endl;
1352 while(!f.eof() && (get_state() != parser_end)){
1354 xmlParseChunk(d_context, d_parse_buffer, chunk_size, 0);
1357 f.read(d_parse_buffer, D4_PARSE_BUFF_SIZE);
1358 chunk_size=f.gcount();
1359 d_parse_buffer[chunk_size]=0;
1360 if (debug) cerr <<
"chunk: (" << chunk_count++ <<
"): " << endl << d_parse_buffer << endl << endl;
1364 xmlParseChunk(d_context, d_parse_buffer, chunk_size, 1);
1388 intern(document.c_str(), document.length(), dest_dmr, debug);
1403 if (!(size > 0))
return;
1409 if (!dest_dmr)
throw InternalErr(__FILE__, __LINE__,
"DMR object is null");
1412 push_state(parser_start);
1413 d_context = xmlCreatePushParserCtxt(&d_dmr_sax_parser,
this, buffer, size,
"stream");
1414 d_context->validate =
true;
1417 xmlParseChunk(d_context, buffer, 0, 1);
virtual D4Attributes * attributes()
D4Attribute * get(const string &fqn)
virtual BaseType * NewVariable(Type t, const string &name) const
void add_dim_nocopy(D4Dimension *dim)
D4Dimension * find_dim(const string &path)
Find the dimension using a path. Using the DAP4 name syntax, lookup a dimension. The dimension must b...
Array * find_map_source(const string &path)
Given a path to an Array that is also a Map, get that Array.
D4Dimensions * dims()
Get the dimensions defined for this Group.
D4EnumDefs * enum_defs()
Get the enumerations defined for this Group.
std::string FQN() const override
void intern(istream &f, DMR *dest_dmr, bool debug=false)
void set_dap_version(const std::string &version_string)
void set_namespace(const std::string &ns)
Set the namespace for this DMR.
void set_request_xml_base(const std::string &xb)
virtual D4BaseTypeFactory * factory()
static std::string getDapNamespaceString(DAPVersion version)
A class for error processing.
A class for software fault reporting.
static void dmr_start_document(void *parser)
static void dmr_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 dmr_ignoreable_whitespace(void *parser, const xmlChar *ch, int len)
static void dmr_get_characters(void *parser, const xmlChar *ch, int len)
static void dmr_end_document(void *parser)
static void dmr_get_cdata(void *parser, const xmlChar *value, int len)
static xmlEntityPtr dmr_get_entity(void *parser, const xmlChar *name)
static void dmr_fatal_error(void *parser, const char *msg,...)
top level DAP object to house generic methods
Type
Identifies the data type.
bool is_simple_type(Type t)
Returns true if the instance is a numeric, string or URL type variable.
string D4type_name(Type t)
Returns the type of the class instance as a string. Supports all DAP4 types and not the DAP2-only typ...
bool is_vector_type(Type t)
Returns true if the instance is a vector (i.e., array) type variable.
bool is_integer_type(Type t)
ObjectType get_type(const string &value)