X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fxmlquery.c;h=4728de64f6c66e18d54d6b030ff2a933e1ebe143;hp=18800f2f201f99c1c929def4c04a97db2808d979;hb=b2bc97df294f5da6c93e1119a42536b23afce8ef;hpb=465343e3b3f2cd797e018b26df19c91a39cbeccf diff --git a/src/xmlquery.c b/src/xmlquery.c index 18800f2..4728de6 100644 --- a/src/xmlquery.c +++ b/src/xmlquery.c @@ -1,36 +1,78 @@ -/* - * Copyright (C) 1995-2005, Index Data ApS - * All rights reserved. - * - * $Id: xmlquery.c,v 1.3 2006-02-02 15:00:58 adam Exp $ - */ - -/** - * \file querytostr.c - * \brief Query / XML conversions +/* This file is part of the YAZ toolkit. + * Copyright (C) Index Data + * See the file LICENSE for details. */ +/** \file xmlquery.c + \brief Query / XML conversions +*/ +#if HAVE_CONFIG_H +#include +#endif #include +#include #include -#if HAVE_XML2 +#if YAZ_HAVE_XML2 #include #include #include #include +#include +#include +#include -void yaz_query2xml_attribute_element(const Z_AttributeElement *element, - xmlNodePtr parent) +static int check_diagnostic(const xmlNode *ptr, ODR odr, + int *error_code, const char **addinfo) +{ + if (ptr && ptr->type == XML_ELEMENT_NODE && + !xmlStrcmp(ptr->name, BAD_CAST "diagnostic")) + { + struct _xmlAttr *attr; + const char *code_str = 0; + const char *addinfo_str = 0; + for (attr = ptr->properties; attr; attr = attr->next) + { + if (!xmlStrcmp(attr->name, BAD_CAST "code") && + attr->children && attr->children->type == XML_TEXT_NODE) + code_str = (const char *) attr->children->content; + else if (!xmlStrcmp(attr->name, BAD_CAST "addinfo") && + attr->children && attr->children->type == XML_TEXT_NODE) + addinfo_str = (const char *) attr->children->content; + else + { + *error_code = 1; + *addinfo = "bad attribute for diagnostic element"; + return 1; + } + } + if (!code_str) + { + *error_code = 1; + *addinfo = "missing @code for diagnostic element"; + return 1; + } + *error_code = atoi(code_str); + if (addinfo_str) + *addinfo = odr_strdup(odr, addinfo_str); + return 1; + } + else + return 0; +} + +static void yaz_query2xml_attribute_element(const Z_AttributeElement *element, + xmlNodePtr parent) { char formstr[30]; const char *setname = 0; - + char oid_name_str[OID_STR_MAX]; + if (element->attributeSet) { - oident *attrset; - attrset = oid_getentbyoid (element->attributeSet); - setname = attrset->desc; + setname = yaz_oid_to_string_buf(element->attributeSet, + 0, oid_name_str); } if (element->which == Z_AttributeValue_numeric) @@ -40,10 +82,11 @@ void yaz_query2xml_attribute_element(const Z_AttributeElement *element, if (setname) xmlNewProp(node, BAD_CAST "set", BAD_CAST setname); - sprintf(formstr, "%d", *element->attributeType); + assert(*element->attributeType > 0 && *element->attributeType < 20); + sprintf(formstr, ODR_INT_PRINTF, *element->attributeType); xmlNewProp(node, BAD_CAST "type", BAD_CAST formstr); - sprintf(formstr, "%d", *element->value.numeric); + sprintf(formstr, ODR_INT_PRINTF, *element->value.numeric); xmlNewProp(node, BAD_CAST "value", BAD_CAST formstr); } else if (element->which == Z_AttributeValue_complex) @@ -52,23 +95,23 @@ void yaz_query2xml_attribute_element(const Z_AttributeElement *element, for (i = 0; ivalue.complex->num_list; i++) { xmlNodePtr node = xmlNewChild(parent, 0, BAD_CAST "attr", 0); - + if (setname) xmlNewProp(node, BAD_CAST "set", BAD_CAST setname); - - sprintf(formstr, "%d", *element->attributeType); + + sprintf(formstr, ODR_INT_PRINTF, *element->attributeType); xmlNewProp(node, BAD_CAST "type", BAD_CAST formstr); - + if (element->value.complex->list[i]->which == Z_StringOrNumeric_string) { - xmlNewProp(node, BAD_CAST "value", BAD_CAST + xmlNewProp(node, BAD_CAST "value", BAD_CAST element->value.complex->list[i]->u.string); } else if (element->value.complex->list[i]->which == Z_StringOrNumeric_numeric) { - sprintf(formstr, "%d", + sprintf(formstr, ODR_INT_PRINTF, *element->value.complex->list[i]->u.numeric); xmlNewProp(node, BAD_CAST "value", BAD_CAST formstr); } @@ -77,8 +120,7 @@ void yaz_query2xml_attribute_element(const Z_AttributeElement *element, } -xmlNodePtr yaz_query2xml_term(const Z_Term *term, - xmlNodePtr parent) +static xmlNodePtr yaz_query2xml_term(const Z_Term *term, xmlNodePtr parent) { xmlNodePtr t = 0; xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "term", 0); @@ -93,8 +135,8 @@ xmlNodePtr yaz_query2xml_term(const Z_Term *term, break; case Z_Term_numeric: type = "numeric"; - sprintf(formstr, "%d", *term->u.numeric); - t = xmlNewText(BAD_CAST formstr); + sprintf(formstr, ODR_INT_PRINTF, *term->u.numeric); + t = xmlNewText(BAD_CAST formstr); break; case Z_Term_characterString: type = "string"; @@ -125,8 +167,8 @@ xmlNodePtr yaz_query2xml_term(const Z_Term *term, return node; } -xmlNodePtr yaz_query2xml_apt(const Z_AttributesPlusTerm *zapt, - xmlNodePtr parent) +static xmlNodePtr yaz_query2xml_apt(const Z_AttributesPlusTerm *zapt, + xmlNodePtr parent) { xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "apt", 0); int num_attributes = zapt->attributes->num_attributes; @@ -139,7 +181,7 @@ xmlNodePtr yaz_query2xml_apt(const Z_AttributesPlusTerm *zapt, } -void yaz_query2xml_operator(Z_Operator *op, xmlNodePtr node) +static void yaz_query2xml_operator(Z_Operator *op, xmlNodePtr node) { const char *type = 0; switch(op->which) @@ -160,11 +202,11 @@ void yaz_query2xml_operator(Z_Operator *op, xmlNodePtr node) return; } xmlNewProp(node, BAD_CAST "type", BAD_CAST type); - + if (op->which == Z_Operator_prox) { char formstr[30]; - + if (op->u.prox->exclusion) { if (*op->u.prox->exclusion) @@ -172,24 +214,25 @@ void yaz_query2xml_operator(Z_Operator *op, xmlNodePtr node) else xmlNewProp(node, BAD_CAST "exclusion", BAD_CAST "false"); } - sprintf(formstr, "%d", *op->u.prox->distance); + sprintf(formstr, ODR_INT_PRINTF, *op->u.prox->distance); xmlNewProp(node, BAD_CAST "distance", BAD_CAST formstr); if (*op->u.prox->ordered) xmlNewProp(node, BAD_CAST "ordered", BAD_CAST "true"); - else + else xmlNewProp(node, BAD_CAST "ordered", BAD_CAST "false"); - - sprintf(formstr, "%d", *op->u.prox->relationType); + + sprintf(formstr, ODR_INT_PRINTF, *op->u.prox->relationType); xmlNewProp(node, BAD_CAST "relationType", BAD_CAST formstr); - + switch(op->u.prox->which) { case Z_ProximityOperator_known: - sprintf(formstr, "%d", *op->u.prox->u.known); + sprintf(formstr, ODR_INT_PRINTF, *op->u.prox->u.known); xmlNewProp(node, BAD_CAST "knownProximityUnit", BAD_CAST formstr); break; + case Z_ProximityOperator_private: default: xmlNewProp(node, BAD_CAST "privateProximityUnit", BAD_CAST "private"); @@ -198,14 +241,14 @@ void yaz_query2xml_operator(Z_Operator *op, xmlNodePtr node) } } -xmlNodePtr yaz_query2xml_rpnstructure(const Z_RPNStructure *zs, - xmlNodePtr parent) +static xmlNodePtr yaz_query2xml_rpnstructure(const Z_RPNStructure *zs, + xmlNodePtr parent) { if (zs->which == Z_RPNStructure_complex) { Z_Complex *zc = zs->u.complex; - xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "binary", 0); + xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "operator", 0); if (zc->roperator) yaz_query2xml_operator(zc->roperator, node); yaz_query2xml_rpnstructure(zc->s1, node); @@ -218,49 +261,52 @@ xmlNodePtr yaz_query2xml_rpnstructure(const Z_RPNStructure *zs, return yaz_query2xml_apt(zs->u.simple->u.attributesPlusTerm, parent); else if (zs->u.simple->which == Z_Operand_resultSetId) - return xmlNewChild(parent, /* NS */ 0, BAD_CAST "rset", + return xmlNewChild(parent, /* NS */ 0, BAD_CAST "rset", BAD_CAST zs->u.simple->u.resultSetId); } return 0; } -xmlNodePtr yaz_query2xml_rpn(const Z_RPNQuery *rpn, xmlNodePtr parent) +static xmlNodePtr yaz_query2xml_rpn(const Z_RPNQuery *rpn, xmlNodePtr parent) { - oident *attrset = oid_getentbyoid (rpn->attributeSetId); - if (attrset && attrset->value) - xmlNewProp(parent, BAD_CAST "set", BAD_CAST attrset->desc); + if (rpn->attributeSetId) + { + char oid_name_str[OID_STR_MAX]; + const char *setname = yaz_oid_to_string_buf(rpn->attributeSetId, + 0, oid_name_str); + if (setname) + xmlNewProp(parent, BAD_CAST "set", BAD_CAST setname); + } return yaz_query2xml_rpnstructure(rpn->RPNStructure, parent); } -xmlNodePtr yaz_query2xml_ccl(const Odr_oct *ccl, xmlNodePtr node) +static xmlNodePtr yaz_query2xml_ccl(const Odr_oct *ccl, xmlNodePtr node) { return 0; } -xmlNodePtr yaz_query2xml_z3958(const Odr_oct *ccl, xmlNodePtr node) +static xmlNodePtr yaz_query2xml_z3958(const Odr_oct *ccl, xmlNodePtr node) { return 0; } -xmlNodePtr yaz_query2xml_cql(const char *cql, xmlNodePtr node) +static xmlNodePtr yaz_query2xml_cql(const char *cql, xmlNodePtr node) { return 0; } -void yaz_rpnquery2xml(const Z_RPNQuery *rpn, void *docp_void) +void yaz_rpnquery2xml(const Z_RPNQuery *rpn, xmlDocPtr *docp) { Z_Query query; query.which = Z_Query_type_1; query.u.type_1 = (Z_RPNQuery *) rpn; - yaz_query2xml(&query, docp_void); + yaz_query2xml(&query, docp); } -void yaz_query2xml(const Z_Query *q, void *docp_void) +void yaz_query2xml(const Z_Query *q, xmlDocPtr *docp) { - xmlDocPtr *docp = (xmlDocPtr *) docp_void; - xmlNodePtr top_node, child_node = 0; - const char *type = 0; + xmlNodePtr top_node, q_node = 0, child_node = 0; assert(q); assert(docp); @@ -269,34 +315,30 @@ void yaz_query2xml(const Z_Query *q, void *docp_void) switch (q->which) { - case Z_Query_type_1: + case Z_Query_type_1: case Z_Query_type_101: - type = "rpn"; - child_node = yaz_query2xml_rpn(q->u.type_1, top_node); + q_node = xmlNewChild(top_node, 0, BAD_CAST "rpn", 0); + child_node = yaz_query2xml_rpn(q->u.type_1, q_node); break; case Z_Query_type_2: - type = "ccl"; - child_node = yaz_query2xml_ccl(q->u.type_2, top_node); + q_node = xmlNewChild(top_node, 0, BAD_CAST "ccl", 0); + child_node = yaz_query2xml_ccl(q->u.type_2, q_node); break; case Z_Query_type_100: - type = "z39.58"; - child_node = yaz_query2xml_z3958(q->u.type_100, top_node); + q_node = xmlNewChild(top_node, 0, BAD_CAST "z39.58", 0); + child_node = yaz_query2xml_z3958(q->u.type_100, q_node); break; case Z_Query_type_104: if (q->u.type_104->which == Z_External_CQL) { - type = "cql"; - child_node = yaz_query2xml_cql(q->u.type_104->u.cql, top_node); + q_node = xmlNewChild(top_node, 0, BAD_CAST "cql", 0); + child_node = yaz_query2xml_cql(q->u.type_104->u.cql, q_node); } } - - if (child_node && type) + if (child_node && q_node) { *docp = xmlNewDoc(BAD_CAST "1.0"); xmlDocSetRootElement(*docp, top_node); /* make it top node in doc */ - - /* set type attribute now */ - xmlNewProp(top_node, BAD_CAST "type", BAD_CAST type); } else { @@ -305,20 +347,493 @@ void yaz_query2xml(const Z_Query *q, void *docp_void) } } -void yaz_xml2query(const xmlNode node, Z_Query **q, ODR odr) +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) +{ + const char *type = yaz_xml_get_prop((xmlNodePtr) ptr, "type"); + if (!type) + { + *error_code = 1; + *addinfo = "no operator type"; + return; + } + *op = (Z_Operator*) odr_malloc(odr, sizeof(Z_Operator)); + if (!strcmp(type, "and")) + { + (*op)->which = Z_Operator_and; + (*op)->u.op_and = odr_nullval(); + } + else if (!strcmp(type, "or")) + { + (*op)->which = Z_Operator_or; + (*op)->u.op_or = odr_nullval(); + } + else if (!strcmp(type, "not")) + { + (*op)->which = Z_Operator_and_not; + (*op)->u.and_not = odr_nullval(); + } + else if (!strcmp(type, "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"; + } +} + +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) { + const xmlNode *ptr = ptr_apt->children; + int i, num_attr = 0; + + *zapt = (Z_AttributesPlusTerm *) + odr_malloc(odr, sizeof(Z_AttributesPlusTerm)); + + /* deal with attributes */ + (*zapt)->attributes = (Z_AttributeList*) + odr_malloc(odr, sizeof(Z_AttributeList)); + + /* how many attributes? */ + for (; ptr; ptr = ptr->next) + if (ptr->type == XML_ELEMENT_NODE) + { + if (!xmlStrcmp(ptr->name, BAD_CAST "attr")) + num_attr++; + else + break; + } + + /* allocate and parse for real */ + (*zapt)->attributes->num_attributes = num_attr; + (*zapt)->attributes->attributes = (Z_AttributeElement **) + odr_malloc(odr, sizeof(Z_AttributeElement*) * num_attr); + + i = 0; + ptr = ptr_apt->children; + for (; ptr; ptr = ptr->next) + if (ptr->type == XML_ELEMENT_NODE) + { + if (!xmlStrcmp(ptr->name, BAD_CAST "attr")) + { + yaz_xml2query_attribute_element( + ptr, &(*zapt)->attributes->attributes[i], odr, + error_code, addinfo); + i++; + } + else + break; + } + if (check_diagnostic(ptr, odr, error_code, addinfo)) + return; + if (ptr && ptr->type == XML_ELEMENT_NODE) + { + if (!xmlStrcmp(ptr->name, BAD_CAST "term")) + { + /* deal with term */ + yaz_xml2query_term(ptr, &(*zapt)->term, odr, error_code, addinfo); + } + else + { + *error_code = 1; + *addinfo = "bad element in apt content"; + } + } + else + { + *error_code = 1; + *addinfo = "missing term node in apt content"; + } +} +static void yaz_xml2query_rset(const xmlNode *ptr, Z_ResultSetId **rset, + ODR odr, int *error_code, const char **addinfo) +{ + if (ptr->children) + { + *rset = strVal(ptr->children, odr); + } + else + { + *error_code = 1; + *addinfo = "missing rset content"; + } } +static void yaz_xml2query_rpnstructure(const xmlNode *ptr, Z_RPNStructure **zs, + ODR odr, + int *error_code, const char **addinfo) +{ + while (ptr && ptr->type != XML_ELEMENT_NODE) + ptr = ptr->next; -/* HAVE_XML2 */ + if (!ptr || ptr->type != XML_ELEMENT_NODE) + { + *error_code = 1; + *addinfo = "missing rpn operator, rset, apt node"; + return; + } + if (check_diagnostic(ptr, odr, error_code, addinfo)) + return; + + *zs = (Z_RPNStructure *) odr_malloc(odr, sizeof(Z_RPNStructure)); + if (!xmlStrcmp(ptr->name, BAD_CAST "operator")) + { + Z_Complex *zc = (Z_Complex *) odr_malloc(odr, sizeof(Z_Complex)); + + (*zs)->which = Z_RPNStructure_complex; + (*zs)->u.complex = zc; + + yaz_xml2query_operator(ptr, &zc->roperator, odr, error_code, addinfo); + + ptr = ptr->children; + while (ptr && ptr->type != XML_ELEMENT_NODE) + ptr = ptr->next; + yaz_xml2query_rpnstructure(ptr, &zc->s1, odr, error_code, addinfo); + if (ptr) + ptr = ptr->next; + while (ptr && ptr->type != XML_ELEMENT_NODE) + ptr = ptr->next; + yaz_xml2query_rpnstructure(ptr, &zc->s2, odr, error_code, addinfo); + } + else + { + Z_Operand *s = (Z_Operand *) odr_malloc(odr, sizeof(Z_Operand)); + (*zs)->which = Z_RPNStructure_simple; + (*zs)->u.simple = s; + if (!xmlStrcmp(ptr->name, BAD_CAST "apt")) + { + s->which = Z_Operand_APT; + yaz_xml2query_apt(ptr, &s->u.attributesPlusTerm, + odr, error_code, addinfo); + } + else if (!xmlStrcmp(ptr->name, BAD_CAST "rset")) + { + s->which = Z_Operand_resultSetId; + yaz_xml2query_rset(ptr, &s->u.resultSetId, + odr, error_code, addinfo); + } + else + { + *error_code = 1; + *addinfo = "bad element: expected binary, apt or rset"; + } + } +} + +static void yaz_xml2query_rpn(const xmlNode *ptr, Z_RPNQuery **query, ODR odr, + int *error_code, const char **addinfo) +{ + const char *set = yaz_xml_get_prop((xmlNodePtr) ptr, "set"); + + *query = (Z_RPNQuery*) odr_malloc(odr, sizeof(Z_RPNQuery)); + if (set) + { + (*query)->attributeSetId = + yaz_string_to_oid_odr(yaz_oid_std(), + CLASS_ATTSET, set, odr); + } + else + (*query)->attributeSetId = 0; + yaz_xml2query_rpnstructure(ptr->children, &(*query)->RPNStructure, + odr, error_code, addinfo); +} + +static void yaz_xml2query_(const xmlNode *ptr, Z_Query **query, ODR odr, + int *error_code, const char **addinfo) +{ + if (check_diagnostic(ptr, odr, error_code, addinfo)) + return; + if (ptr && ptr->type == XML_ELEMENT_NODE && + !xmlStrcmp(ptr->name, BAD_CAST "query")) + { + const char *type; + ptr = ptr->children; + while (ptr && ptr->type != XML_ELEMENT_NODE) + ptr = ptr->next; + if (!ptr || ptr->type != XML_ELEMENT_NODE) + { + *error_code = 1; + *addinfo = "missing query content"; + return; + } + type = (const char *) ptr->name; + + *query = (Z_Query*) odr_malloc(odr, sizeof(Z_Query)); + if (!type || !strcmp(type, "rpn")) + { + (*query)->which = Z_Query_type_1; + yaz_xml2query_rpn(ptr, &(*query)->u.type_1, odr, + error_code, addinfo); + } + else if (!strcmp(type, "ccl")) + { + *error_code = 1; + *addinfo = "ccl not supported yet"; + } + else if (!strcmp(type, "z39.58")) + { + *error_code = 1; + *addinfo = "z39.58 not supported yet"; + } + else if (!strcmp(type, "cql")) + { + *error_code = 1; + *addinfo = "cql not supported yet"; + } + else + { + *error_code = 1; + *addinfo = "unsupported query type"; + } + } + else + { + *error_code = 1; + *addinfo = "missing query element"; + } +} + +void yaz_xml2query(const xmlNode *xmlnodep, Z_Query **query, ODR odr, + int *error_code, const char **addinfo) +{ + yaz_xml2query_(xmlnodep, query, odr, error_code, addinfo); +} + +/* YAZ_HAVE_XML2 */ #endif /* * Local variables: * c-basic-offset: 4 + * c-file-style: "Stroustrup" * indent-tabs-mode: nil * End: * vim: shiftwidth=4 tabstop=8 expandtab */ +