yaz_query2xml complete and tested
authorAdam Dickmeiss <adam@indexdata.dk>
Mon, 30 Jan 2006 14:02:06 +0000 (14:02 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Mon, 30 Jan 2006 14:02:06 +0000 (14:02 +0000)
include/yaz/test.h
include/yaz/xmlquery.h
src/test.c
src/xmlquery.c
test/tstxmlquery.c

index 6d767bb..ac4f879 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2005, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: test.h,v 1.3 2006-01-29 21:59:12 adam Exp $
+ * $Id: test.h,v 1.4 2006-01-30 14:02:06 adam Exp $
  */
 
 #ifndef YAZ_TEST_H
   } \
 }
 
+#define YAZ_CHECK_EQ(left, right) { \
+  int lval = left; \
+  int rval = right; \
+  if (lval == rval) { \
+    yaz_check_eq1(YAZ_TEST_TYPE_OK, __FILE__, __LINE__, \
+     #left, #right, lval, rval); \
+  } else { \
+    yaz_check_eq1(YAZ_TEST_TYPE_FAIL, __FILE__, __LINE__, \
+     #left, #right, lval, rval); \
+  } \
+}
+
 #define YAZ_CHECK_INIT(argc, argv) yaz_check_init1(&argc, &argv)
 #define YAZ_CHECK_TERM yaz_check_term1(); return 0
 
@@ -30,8 +42,11 @@ YAZ_EXPORT void yaz_check_init1(int *argc, char ***argv);
 YAZ_EXPORT void yaz_check_term1(void);
 YAZ_EXPORT void yaz_check_print1(int type, const char *file, int line,
                                  const char *expr);
-YAZ_END_CDECL
+YAZ_EXPORT void yaz_check_eq1(int type, const char *file, int line,
+                              const char *left, const char *right,
+                              int lval, int rval);
 
+YAZ_END_CDECL
 
 #endif
 /*
index 3f83875..ff5d5fb 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2005, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: xmlquery.h,v 1.1 2006-01-27 17:28:16 adam Exp $
+ * $Id: xmlquery.h,v 1.2 2006-01-30 14:02:06 adam Exp $
  */
 
 #ifndef YAZ_XMLQUERY_H
@@ -14,6 +14,7 @@
 YAZ_BEGIN_CDECL
 
 YAZ_EXPORT void yaz_query2xml(const Z_Query *q, void *docp_void);
+YAZ_EXPORT void yaz_rpnquery2xml(const Z_RPNQuery *rpn, void *docp_void);
 
 YAZ_END_CDECL
 
index 967b53b..0138056 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2005, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: test.c,v 1.3 2006-01-29 21:59:13 adam Exp $
+ * $Id: test.c,v 1.4 2006-01-30 14:02:07 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
@@ -118,7 +118,17 @@ void yaz_check_term1(void)
     exit(0);
 }
 
-void yaz_check_print1(int type, const char *file, int line, const char *expr)
+void yaz_check_eq1(int type, const char *file, int line,
+                   const char *left, const char *right, int lval, int rval)
+{
+    char formstr[2048];
+    
+    sprintf(formstr, "%.500s != %.500s\n%d != %d", left, right, lval, rval);
+    yaz_check_print1(type, file, line, formstr);
+}
+
+void yaz_check_print1(int type, const char *file, int line, 
+                      const char *expr)
 {
     const char *msg = "unknown";
 
@@ -137,7 +147,8 @@ void yaz_check_print1(int type, const char *file, int line, const char *expr)
             return;
         break;
     }
-    fprintf(get_file(), "%s:%d %s: %s\n", file, line, msg, expr);
+    fprintf(get_file(), "%s:%d %s: ", file, line, msg);
+    fprintf(get_file(), "%s\n", expr);
 }
 
 
index 515206e..b83449f 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2005, Index Data ApS
  * All rights reserved.
  *
- * $Id: xmlquery.c,v 1.1 2006-01-27 17:28:16 adam Exp $
+ * $Id: xmlquery.c,v 1.2 2006-01-30 14:02:07 adam Exp $
  */
 
 /**
 #include <yaz/logrpn.h>
 #include <yaz/xmlquery.h>
 
-xmlNodePtr yaz_query2xml_attribute_element(const Z_AttributeElement *element,
-                                          xmlNodePtr parent)
+void yaz_query2xml_attribute_element(const Z_AttributeElement *element,
+                                     xmlNodePtr parent)
 {
-    xmlNodePtr node = xmlNewChild(parent, 0, BAD_CAST "attr", 0);
-#if 0
-    int i;
-    char *setname  = 0;
+    char formstr[30];
+    const char *setname = 0;
+    
     if (element->attributeSet)
     {
         oident *attrset;
         attrset = oid_getentbyoid (element->attributeSet);
         setname = attrset->desc;
     }
-    switch (element->which) 
+
+    if (element->which == Z_AttributeValue_numeric)
     {
-    case Z_AttributeValue_numeric:
-        wrbuf_printf(b,"@attr %s%s%d=%d ", setname, sep,
-                     *element->attributeType, *element->value.numeric);
-        break;
-    case Z_AttributeValue_complex:
-        wrbuf_printf(b,"@attr %s%s\"%d=", setname, sep,
-                     *element->attributeType);
+        xmlNodePtr node = xmlNewChild(parent, 0, BAD_CAST "attr", 0);
+
+        if (setname)
+            xmlNewProp(node, BAD_CAST "set", BAD_CAST setname);
+
+        sprintf(formstr, "%d", *element->attributeType);
+        xmlNewProp(node, BAD_CAST "type", BAD_CAST formstr);
+
+        sprintf(formstr, "%d", *element->value.numeric);
+        xmlNewProp(node, BAD_CAST "value", BAD_CAST formstr);
+    }
+    else if (element->which == Z_AttributeValue_complex)
+    {
+        int i;
         for (i = 0; i<element->value.complex->num_list; i++)
         {
-            if (i)
-                wrbuf_printf(b,",");
+            xmlNodePtr node = xmlNewChild(parent, 0, BAD_CAST "attr", 0);
+            
+            if (setname)
+                xmlNewProp(node, BAD_CAST "set", BAD_CAST setname);
+            
+            sprintf(formstr, "%d", *element->attributeType);
+            xmlNewProp(node, BAD_CAST "type", BAD_CAST formstr);
+            
             if (element->value.complex->list[i]->which ==
                 Z_StringOrNumeric_string)
-                wrbuf_printf (b, "%s",
-                              element->value.complex->list[i]->u.string);
+            {
+                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)
-                wrbuf_printf (b, "%d", 
-                              *element->value.complex->list[i]->u.numeric);
+            {
+                sprintf(formstr, "%d",
+                        *element->value.complex->list[i]->u.numeric);
+                xmlNewProp(node, BAD_CAST "value", BAD_CAST formstr);
+            }
         }
-        wrbuf_printf(b, "\" ");
-        break;
-    default:
-        wrbuf_printf (b, "@attr 1=unknown ");
     }
-#endif
-    return node;
 }
 
 
@@ -107,47 +119,79 @@ xmlNodePtr yaz_query2xml_apt(const Z_AttributesPlusTerm *zapt,
     return node;
 }
 
-xmlNodePtr yaz_query2xml_rpnstructure(const Z_RPNStructure *zs,
-                                     xmlNodePtr parent)
+
+void yaz_query2xml_operator(Z_Operator *op, xmlNodePtr node)
 {
-    if (zs->which == Z_RPNStructure_complex)
+    const char *type = 0;
+    switch(op->which)
     {
-       return 0;
-#if 0
-        Z_Operator *op = zs->u.complex->roperator;
-        wrbuf_printf(b, "@%s ", complex_op_name(op) );
-        if (op->which== Z_Operator_prox)
+    case Z_Operator_and:
+        type = "and";
+        break;
+    case Z_Operator_or:
+        type = "or";
+        break;
+    case Z_Operator_and_not:
+        type = "not";
+        break;
+    case Z_Operator_prox:
+        type = "prox";
+        break;
+    default:
+        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)
-                wrbuf_putc(b, 'n');
-            else if (*op->u.prox->exclusion)
-                wrbuf_putc(b, '1');
+            if (*op->u.prox->exclusion)
+                xmlNewProp(node, BAD_CAST "exclusion", BAD_CAST "true");
             else
-                wrbuf_putc(b, '0');
-
-            wrbuf_printf(b, " %d %d %d ", *op->u.prox->distance,
-                         *op->u.prox->ordered,
-                         *op->u.prox->relationType);
+                xmlNewProp(node, BAD_CAST "exclusion", BAD_CAST "false");
+        }
+        sprintf(formstr, "%d", *op->u.prox->distance);
+        xmlNewProp(node, BAD_CAST "distance", BAD_CAST formstr);
 
-            switch(op->u.prox->which)
-            {
-            case Z_ProximityOperator_known:
-                wrbuf_putc(b, 'k');
-                break;
-            case Z_ProximityOperator_private:
-                wrbuf_putc(b, 'p');
-                break;
-            default:
-                wrbuf_printf(b, "%d", op->u.prox->which);
-            }
-            if (op->u.prox->u.known)
-                wrbuf_printf(b, " %d ", *op->u.prox->u.known);
-            else
-                wrbuf_printf(b, " 0 ");
+        if (*op->u.prox->ordered)
+            xmlNewProp(node, BAD_CAST "ordered", BAD_CAST "true");
+        else 
+            xmlNewProp(node, BAD_CAST "ordered", BAD_CAST "false");
+       
+        sprintf(formstr, "%d", *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);
+            xmlNewProp(node, BAD_CAST "knownProximityUnit",
+                       BAD_CAST formstr);
+            break;
+        default:
+            xmlNewProp(node, BAD_CAST "privateProximityUnit",
+                       BAD_CAST "private");
+            break;
         }
-        yaz_rpnstructure_to_wrbuf(b,zs->u.complex->s1);
-        yaz_rpnstructure_to_wrbuf(b,zs->u.complex->s2);
-#endif
+    }
+}
+
+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);
+        if (zc->roperator)
+            yaz_query2xml_operator(zc->roperator, node);
+        yaz_query2xml_rpnstructure(zc->s1, node);
+        yaz_query2xml_rpnstructure(zc->s2, node);
+        return node;
     }
     else if (zs->which == Z_RPNStructure_simple)
     {
@@ -155,15 +199,8 @@ 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 0;
-#if 0
-            yaz_term_to_wrbuf(b, zs->u.simple->u.resultSetId,
-                              strlen(zs->u.simple->u.resultSetId));
-#endif
-        }
-        else
-           return 0;
+            return xmlNewChild(parent, /* NS */ 0, BAD_CAST "rset", 
+                               BAD_CAST zs->u.simple->u.resultSetId);
     }
     return 0;
 }
@@ -172,8 +209,7 @@ xmlNodePtr yaz_query2xml_rpn(const Z_RPNQuery *rpn, xmlNodePtr parent)
 {
     oident *attrset = oid_getentbyoid (rpn->attributeSetId);
     if (attrset && attrset->value)
-       parent = xmlNewChild(parent, /*ns */ 0,
-                            BAD_CAST "attrset", BAD_CAST attrset->desc);
+        xmlNewProp(parent, BAD_CAST "set", BAD_CAST attrset->desc);
     return yaz_query2xml_rpnstructure(rpn->RPNStructure, parent);
 }
 
@@ -192,6 +228,15 @@ xmlNodePtr yaz_query2xml_cql(const char *cql, xmlNodePtr node)
     return 0;
 }
 
+void yaz_rpnquery2xml(const Z_RPNQuery *rpn, void *docp_void)
+{
+    Z_Query query;
+
+    query.which = Z_Query_type_1;
+    query.u.type_1 = (Z_RPNQuery *) rpn;
+    yaz_query2xml(&query, docp_void);
+}
+
 void yaz_query2xml(const Z_Query *q, void *docp_void)
 {
     xmlDocPtr *docp = (xmlDocPtr *) docp_void;
index 155232f..625d5e2 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2005, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: tstxmlquery.c,v 1.5 2006-01-30 08:08:23 adam Exp $
+ * $Id: tstxmlquery.c,v 1.6 2006-01-30 14:02:07 adam Exp $
  */
 
 #include <stdlib.h>
 #include <yaz/pquery.h>
 #include <yaz/test.h>
 
-static void pqf2xml_text(const char *pqf)
+#if HAVE_XML2
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#endif
+
+enum pqf2xml_status {
+    PQF_FAILED,
+    QUERY2XML_FAILED,
+    XML_NO_MATCH,
+    XML_MATCH,
+    XML_NO_ERROR
+};
+
+enum pqf2xml_status pqf2xml_text(const char *pqf, const char *expect_xml)
 {
     YAZ_PQF_Parser parser = yaz_pqf_create();
     ODR odr = odr_createmem(ODR_ENCODE);
     Z_RPNQuery *rpn;
-    Z_Query *query;
+    enum pqf2xml_status status = XML_NO_ERROR;
 
     YAZ_CHECK(parser);
 
@@ -26,16 +39,111 @@ static void pqf2xml_text(const char *pqf)
 
     rpn = yaz_pqf_parse(parser, odr, pqf);
 
-    YAZ_CHECK(rpn);
-
     yaz_pqf_destroy(parser);
 
-    query = odr_malloc(odr, sizeof(*query));
-    query->which = Z_Query_type_1;
-    query->u.type_1 = rpn;
-
+    if (!rpn)
+        status = PQF_FAILED;
+    else
+    {
+        status = QUERY2XML_FAILED;
+#if HAVE_XML2
+        xmlDocPtr doc = 0;
+        yaz_rpnquery2xml(rpn, &doc);
+        
+        if (!doc)
+            status = QUERY2XML_FAILED;
+        else
+        {
+            char *buf_out;
+            int len_out;
+
+            xmlDocDumpMemory(doc, (xmlChar **) &buf_out, &len_out);
+            
+            if (len_out == strlen(expect_xml)
+                && memcmp(buf_out, expect_xml, len_out) == 0)
+            {
+                status = XML_MATCH;
+            }
+            else
+            {
+                printf("%.*s\n", len_out, buf_out);
+                status = XML_NO_MATCH;
+            }
+            xmlFreeDoc(doc);
+        }
+#endif
+    }
     odr_destroy(odr);
+    return status;
+}
+
+void tst()
+{
+    YAZ_CHECK_EQ(pqf2xml_text("@attr 1=4 bad query", ""), PQF_FAILED);
 #if HAVE_XML2
+    YAZ_CHECK_EQ(pqf2xml_text(
+                     "@attr 1=4 computer", 
+                     "<?xml version=\"1.0\"?>\n"
+                     "<query set=\"Bib-1\" type=\"rpn\">"
+                     "<apt><attr type=\"1\" value=\"4\"/>"
+                     "<term>computer</term></apt>"
+                     "</query>\n"), XML_MATCH);
+    
+    YAZ_CHECK_EQ(pqf2xml_text(
+                     "@attr 2=1 @attr 1=title computer",
+                     "<?xml version=\"1.0\"?>\n"
+                     "<query set=\"Bib-1\" type=\"rpn\">"
+                     "<apt><attr type=\"1\" value=\"title\"/>"
+                     "<attr type=\"2\" value=\"1\"/>"
+                     "<term>computer</term></apt>"
+                     "</query>\n"), XML_MATCH);
+
+    YAZ_CHECK_EQ(pqf2xml_text(
+                     "@attr 2=1 @attr exp1 1=1 computer",
+                     "<?xml version=\"1.0\"?>\n"
+                     "<query set=\"Bib-1\" type=\"rpn\">"
+                     "<apt><attr set=\"Exp-1\" type=\"1\" value=\"1\"/>"
+                     "<attr type=\"2\" value=\"1\"/>"
+                     "<term>computer</term></apt>"
+                     "</query>\n"), XML_MATCH);
+    
+    YAZ_CHECK_EQ(pqf2xml_text(
+                     "@and a b", 
+                     "<?xml version=\"1.0\"?>\n"
+                     "<query set=\"Bib-1\" type=\"rpn\">"
+                     "<binary type=\"and\">"
+                     "<apt><term>a</term></apt><apt><term>b</term></apt>"
+                     "</binary></query>\n"), XML_MATCH);
+    
+    YAZ_CHECK_EQ(pqf2xml_text(
+                     "@or @and a b c", 
+                     "<?xml version=\"1.0\"?>\n"
+                     "<query set=\"Bib-1\" type=\"rpn\">"
+                     "<binary type=\"or\">"
+                     "<binary type=\"and\"><apt><term>a</term></apt>"
+                     "<apt><term>b</term></apt></binary>"
+                     "<apt><term>c</term></apt>"
+                     "</binary></query>\n"), XML_MATCH);
+
+    YAZ_CHECK_EQ(pqf2xml_text(
+                     "@set abe", 
+                     "<?xml version=\"1.0\"?>\n"
+                     "<query set=\"Bib-1\" type=\"rpn\">"
+                     "<rset>abe</rset></query>\n"), XML_MATCH);
+
+    YAZ_CHECK_EQ(pqf2xml_text(
+                     /* exclusion, distance, ordered, relationtype, 
+                        knownunit, proxunit */
+                     "@prox 0 3 1 2 k 2           a b", 
+                     "<?xml version=\"1.0\"?>\n"
+                     "<query set=\"Bib-1\" type=\"rpn\">"
+                     "<binary type=\"prox\" exclusion=\"false\" "
+                     "distance=\"3\" "
+                     "ordered=\"true\" "
+                     "relationType=\"2\" "
+                     "knownProximityUnit=\"2\">"
+                     "<apt><term>a</term></apt><apt><term>b</term></apt>"
+                     "</binary></query>\n"), XML_MATCH);
 
 #endif
 }
@@ -43,9 +151,7 @@ static void pqf2xml_text(const char *pqf)
 int main (int argc, char **argv)
 {
     YAZ_CHECK_INIT(argc, argv);
-
-    pqf2xml_text("@attr 1=4 computer");
-
+    tst();
     YAZ_CHECK_TERM;
 }