+static bool_t *boolVal(ODR odr, const char *str)
+{
+ if (*str == '\0' || strchr("0fF", *str))
+ return odr_booldup(odr, 0);
+ return odr_booldup(odr, 1);
+}
+
+static Odr_int *intVal(ODR odr, const char *str)
+{
+ return odr_intdup(odr, atoi(str));
+}
+
+static void yaz_xml2query_operator(const xmlNode *ptr, Z_Operator **op,
+ ODR odr,
+ int *error_code, const char **addinfo)
+{
+ xmlChar *type = xmlGetProp((xmlNodePtr) ptr, BAD_CAST "type");
+ if (!type)
+ {
+ *error_code = 1;
+ *addinfo = "no operator type";
+ return;
+ }
+ *op = (Z_Operator*) odr_malloc(odr, sizeof(Z_Operator));
+ if (!xmlStrcmp(type, BAD_CAST "and"))
+ {
+ (*op)->which = Z_Operator_and;
+ (*op)->u.op_and = odr_nullval();
+ }
+ else if (!xmlStrcmp(type, BAD_CAST "or"))
+ {
+ (*op)->which = Z_Operator_or;
+ (*op)->u.op_or = odr_nullval();
+ }
+ else if (!xmlStrcmp(type, BAD_CAST "not"))
+ {
+ (*op)->which = Z_Operator_and_not;
+ (*op)->u.and_not = odr_nullval();
+ }
+ else if (!xmlStrcmp(type, BAD_CAST "prox"))
+ {
+ struct _xmlAttr *attr;
+ Z_ProximityOperator *pop = (Z_ProximityOperator *)
+ odr_malloc(odr, sizeof(*pop));
+ (*op)->which = Z_Operator_prox;
+ (*op)->u.prox = pop;
+ /* default values */
+ pop->exclusion = 0;
+ pop->ordered = odr_booldup(odr, 1);
+ pop->relationType =
+ odr_intdup(odr, Z_ProximityOperator_Prox_lessThanOrEqual);
+ pop->which = Z_ProximityOperator_known;
+ pop->u.known = odr_intdup(odr, Z_ProxUnit_word);
+ pop->distance = odr_intdup(odr, 1);
+
+ for (attr = ptr->properties; attr; attr = attr->next)
+ {
+ const char *value = (const char *) attr->children->content;
+ if (!xmlStrcmp(attr->name, BAD_CAST "type"))
+ ;
+ else if (!xmlStrcmp(attr->name, BAD_CAST "exclusion"))
+ pop->exclusion = boolVal(odr, value);
+ else if (!xmlStrcmp(attr->name, BAD_CAST "distance"))
+ pop->distance = intVal(odr, value);
+ else if (!xmlStrcmp(attr->name, BAD_CAST "ordered"))
+ pop->ordered = boolVal(odr, value);
+ else if (!xmlStrcmp(attr->name, BAD_CAST "relationType"))
+ pop->relationType = intVal(odr, value);
+ else if (!xmlStrcmp(attr->name, BAD_CAST "knownProximityUnit"))
+ {
+ pop->which = Z_ProximityOperator_known;
+ pop->u.known = intVal(odr, value);
+ }
+ else if (!xmlStrcmp(attr->name, BAD_CAST "privateProximityUnit"))
+ {
+ pop->which = Z_ProximityOperator_private;
+ pop->u.known = intVal(odr, value);
+ }
+ else
+ {
+ *error_code = 1;
+ *addinfo = "bad proximity attribute";
+ break;
+ }
+ }
+ }
+ else
+ {
+ *error_code = 1;
+ *addinfo = "bad operator type";
+ }
+ xmlFree(type);
+}
+
+static void yaz_xml2query_attribute_element(const xmlNode *ptr,
+ Z_AttributeElement **elem, ODR odr,
+ int *error_code,
+ const char **addinfo)
+{
+ int i;
+ xmlChar *set = 0;
+ xmlChar *type = 0;
+ xmlChar *value = 0;
+ int num_values = 0;
+ struct _xmlAttr *attr;
+ for (attr = ptr->properties; attr; attr = attr->next)
+ {
+ if (!xmlStrcmp(attr->name, BAD_CAST "set") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ set = attr->children->content;
+ else if (!xmlStrcmp(attr->name, BAD_CAST "type") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ type = attr->children->content;
+ else if (!xmlStrcmp(attr->name, BAD_CAST "value") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ {
+ value = attr->children->content;
+ num_values++;
+ }
+ else
+ {
+ *error_code = 1;
+ *addinfo = "bad attribute for attr content";
+ return;
+ }
+ }
+ if (!type)
+ {
+ *error_code = 1;
+ *addinfo = "missing type attribute for att content";
+ return;
+ }
+ if (!value)
+ {
+ *error_code = 1;
+ *addinfo = "missing value attribute for att content";
+ return;
+ }
+
+ *elem = (Z_AttributeElement *) odr_malloc(odr, sizeof(**elem));
+ if (set)
+ (*elem)->attributeSet = yaz_string_to_oid_odr(yaz_oid_std(),
+ CLASS_ATTSET,
+ (const char *) set,
+ odr);
+ else
+ (*elem)->attributeSet = 0;
+ (*elem)->attributeType = intVal(odr, (const char *) type);
+
+ /* looks like a number ? */
+ for (i = 0; value[i] && value[i] >= '0' && value[i] <= '9'; i++)
+ ;
+ if (num_values > 1 || value[i])
+ { /* multiple values or string, so turn to complex attribute */
+ (*elem)->which = Z_AttributeValue_complex;
+ (*elem)->value.complex =
+ (Z_ComplexAttribute*) odr_malloc(odr, sizeof(Z_ComplexAttribute));
+ (*elem)->value.complex->num_list = num_values;
+ (*elem)->value.complex->list = (Z_StringOrNumeric **)
+ odr_malloc(odr, sizeof(Z_StringOrNumeric*) * num_values);
+
+ /* second pass over attr values */
+ i = 0;
+ for (attr = ptr->properties; attr; attr = attr->next)
+ {
+ if (!xmlStrcmp(attr->name, BAD_CAST "value") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ {
+ const char *val = (const char *) attr->children->content;
+ assert (i < num_values);
+ (*elem)->value.complex->list[i] = (Z_StringOrNumeric *)
+ odr_malloc(odr, sizeof(Z_StringOrNumeric));
+ (*elem)->value.complex->list[i]->which =
+ Z_StringOrNumeric_string;
+ (*elem)->value.complex->list[i]->u.string =
+ odr_strdup(odr, val);
+ i++;
+ }
+ }
+ (*elem)->value.complex->num_semanticAction = 0;
+ (*elem)->value.complex->semanticAction = 0;
+ }
+ else
+ { /* good'ld numeric value */
+ (*elem)->which = Z_AttributeValue_numeric;
+ (*elem)->value.numeric = intVal(odr, (const char *) value);
+ }
+}
+
+static char *strVal(const xmlNode *ptr_cdata, ODR odr)
+{
+ return nmem_text_node_cdata(ptr_cdata, odr_getmem(odr));
+}
+
+static void yaz_xml2query_term(const xmlNode *ptr, Z_Term **term, ODR odr,
+ int *error_code, const char **addinfo)
+{
+ xmlChar *type = 0;
+ struct _xmlAttr *attr;
+ char *cdata = strVal(ptr->children, odr);
+
+ for (attr = ptr->properties; attr; attr = attr->next)
+ {
+ if (!xmlStrcmp(attr->name, BAD_CAST "type") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ type = attr->children->content;
+ else
+ {
+ *error_code = 1;
+ *addinfo = "bad attribute for attr content";
+ return;
+ }
+ }
+ *term = (Z_Term *) odr_malloc(odr, sizeof(Z_Term));
+
+ if (!type || !xmlStrcmp(type, BAD_CAST "general"))
+ {
+ (*term)->which = Z_Term_general;
+ (*term)->u.general =
+ odr_create_Odr_oct(odr, cdata, strlen(cdata));
+ }
+ else if (!xmlStrcmp(type, BAD_CAST "numeric"))
+ {
+ (*term)->which = Z_Term_numeric;
+ (*term)->u.numeric = intVal(odr, cdata);
+ }
+ else if (!xmlStrcmp(type, BAD_CAST "string"))
+ {
+ (*term)->which = Z_Term_characterString;
+ (*term)->u.characterString = cdata;
+ }
+ else if (!xmlStrcmp(type, BAD_CAST "oid"))
+ {
+ *error_code = 1;
+ *addinfo = "unhandled term type: oid";
+ }
+ else if (!xmlStrcmp(type, BAD_CAST "dateTime"))
+ {
+ *error_code = 1;
+ *addinfo = "unhandled term type: dateTime";
+ }
+ else if (!xmlStrcmp(type, BAD_CAST "integerAndUnit"))
+ {
+ *error_code = 1;
+ *addinfo = "unhandled term type: integerAndUnit";
+ }
+ else if (!xmlStrcmp(type, BAD_CAST "null"))
+ {
+ (*term)->which = Z_Term_null;
+ (*term)->u.null = odr_nullval();
+ }
+ else
+ {
+ *error_code = 1;
+ *addinfo = "unhandled term type";
+ }
+}
+
+static void yaz_xml2query_apt(const xmlNode *ptr_apt,
+ Z_AttributesPlusTerm **zapt, ODR odr,
+ int *error_code, const char **addinfo)