Allow yaz_xml2query to throw a certain diagnostic
[yaz-moved-to-github.git] / src / xmlquery.c
index 60b0bc6..db85df0 100644 (file)
 #include <yaz/nmem_xml.h>
 #include <yaz/oid_db.h>
 
+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;
+}
+
 void yaz_query2xml_attribute_element(const Z_AttributeElement *element,
                                      xmlNodePtr parent)
 {
@@ -40,10 +79,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)
@@ -56,7 +96,7 @@ void yaz_query2xml_attribute_element(const Z_AttributeElement *element,
             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 ==
@@ -68,7 +108,7 @@ void yaz_query2xml_attribute_element(const Z_AttributeElement *element,
             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);
             }
@@ -93,7 +133,7 @@ xmlNodePtr yaz_query2xml_term(const Z_Term *term,
         break;
     case Z_Term_numeric:
         type = "numeric";
-       sprintf(formstr, "%d", *term->u.numeric);
+       sprintf(formstr, ODR_INT_PRINTF, *term->u.numeric);
        t = xmlNewText(BAD_CAST formstr);       
         break;
     case Z_Term_characterString:
@@ -172,7 +212,7 @@ 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)
@@ -180,13 +220,13 @@ void yaz_query2xml_operator(Z_Operator *op, xmlNodePtr node)
         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;
@@ -308,11 +348,11 @@ void yaz_query2xml(const Z_Query *q, xmlDocPtr *docp)
 bool_t *boolVal(ODR odr, const char *str)
 {
     if (*str == '\0' || strchr("0fF", *str))
-        return odr_intdup(odr, 0);
-    return odr_intdup(odr, 1);
+        return odr_booldup(odr, 0);
+    return odr_booldup(odr, 1);
 }
 
-int *intVal(ODR odr, const char *str)
+Odr_int *intVal(ODR odr, const char *str)
 {
     return odr_intdup(odr, atoi(str));
 }
@@ -372,7 +412,7 @@ void yaz_xml2query_operator(const xmlNode *ptr, Z_Operator **op,
         if (atval)
             pop->ordered = boolVal(odr, atval);
         else
-            pop->ordered = odr_intdup(odr, 1);
+            pop->ordered = odr_booldup(odr, 1);
 
         atval = (const char *) xmlGetProp((xmlNodePtr) ptr,
                                           BAD_CAST "relationType");
@@ -618,6 +658,9 @@ void yaz_xml2query_apt(const xmlNode *ptr_apt,
             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"))
@@ -664,6 +707,9 @@ void yaz_xml2query_rpnstructure(const xmlNode *ptr, Z_RPNStructure **zs,
         *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"))
     {
@@ -728,6 +774,8 @@ void yaz_xml2query_rpn(const xmlNode *ptr, Z_RPNQuery **query, ODR odr,
 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"))
     {
@@ -790,7 +838,9 @@ void yaz_xml2query(const xmlNode *xmlnodep, Z_Query **query, ODR odr,
 /*
  * Local variables:
  * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
  * indent-tabs-mode: nil
  * End:
  * vim: shiftwidth=4 tabstop=8 expandtab
  */
+