Rename yaz_use_attribute_create to zget_AttributeList_use_string
[yaz-moved-to-github.git] / src / srw.c
index 17b7c39..5076ecc 100644 (file)
--- a/src/srw.c
+++ b/src/srw.c
@@ -1,5 +1,5 @@
 /* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2013 Index Data
+ * Copyright (C) Index Data
  * See the file LICENSE for details.
  */
 /**
@@ -19,6 +19,7 @@
 #include <libxml/tree.h>
 #include <assert.h>
 #include <yaz/facet.h>
+#include <yaz/proto.h>
 #include "sru-p.h"
 
 char *yaz_negotiate_sru_version(char *input_ver)
@@ -113,7 +114,11 @@ static int yaz_srw_record(ODR o, xmlNodePtr pptr, Z_SRW_record *rec,
         int pack = rec->recordPacking;
         const char *spack = yaz_srw_pack_to_str(pack);
 
-        add_xsd_string(ptr, "recordSchema", rec->recordSchema);
+        /* recordSchema and recordData are required */
+        if (!rec->recordSchema)
+            xmlNewChild(ptr, 0, BAD_CAST "recordSchema", 0);
+        else
+            add_xsd_string(ptr, "recordSchema", rec->recordSchema);
         if (spack)
         {
             if (version2)
@@ -121,20 +126,25 @@ static int yaz_srw_record(ODR o, xmlNodePtr pptr, Z_SRW_record *rec,
             else
                 add_xsd_string(ptr, "recordPacking", spack);
         }
-        switch (pack)
+        if (!rec->recordData_buf)
+            xmlNewChild(ptr, 0, BAD_CAST "recordData", 0);
+        else
         {
-        case Z_SRW_recordPacking_string:
-            add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
-                             rec->recordData_len);
-            break;
-        case Z_SRW_recordPacking_XML:
-            add_XML_n(ptr, "recordData", rec->recordData_buf,
-                      rec->recordData_len, 0);
-            break;
-        case Z_SRW_recordPacking_URL:
-            add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
-                             rec->recordData_len);
-            break;
+            switch (pack)
+            {
+            case Z_SRW_recordPacking_string:
+                add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
+                                 rec->recordData_len);
+                break;
+            case Z_SRW_recordPacking_XML:
+                add_XML_n(ptr, "recordData", rec->recordData_buf,
+                          rec->recordData_len, 0);
+                break;
+            case Z_SRW_recordPacking_URL:
+                add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
+                                 rec->recordData_len);
+                break;
+            }
         }
         if (rec->recordPosition)
             add_xsd_integer(ptr, "recordPosition", rec->recordPosition );
@@ -298,7 +308,7 @@ static Z_FacetField *yaz_sru_proxy_decode_facet_field(ODR odr, xmlNodePtr ptr)
     const char* name = yaz_element_attribute_value_get(ptr, "facet", "code");
     yaz_log(YLOG_DEBUG, "sru-proxy facet type: %s", name);
 
-    list = yaz_use_attribute_create(odr, name);
+    list = zget_AttributeList_use_string(odr, name);
     for (node = ptr->children; node; node = node->next) {
         if (yaz_match_xsd_element(node, "facetvalue"))
             num_terms++;
@@ -427,7 +437,8 @@ int sru_decode_surrogate_diagnostics(const char *buf, size_t len,
 }
 
 static int yaz_srw_diagnostics(ODR o, xmlNodePtr pptr, Z_SRW_diagnostic **recs,
-                               int *num, void *client_data, const char *ns)
+                               int *num, void *client_data, const char *ns,
+                               int version2)
 {
     if (o->direction == ODR_DECODE)
     {
@@ -437,7 +448,9 @@ static int yaz_srw_diagnostics(ODR o, xmlNodePtr pptr, Z_SRW_diagnostic **recs,
     {
         int i;
         xmlNsPtr ns_diag =
-            xmlNewNs(pptr, BAD_CAST YAZ_XMLNS_DIAG_v1_1, BAD_CAST "diag" );
+            xmlNewNs(pptr, BAD_CAST (version2 ?
+                                     YAZ_XMLNS_DIAG_v2 : YAZ_XMLNS_DIAG_v1_1),
+                     BAD_CAST "diag" );
         for (i = 0; i < *num; i++)
         {
             const char *std_diag = "info:srw/diagnostic/1/";
@@ -445,6 +458,7 @@ static int yaz_srw_diagnostics(ODR o, xmlNodePtr pptr, Z_SRW_diagnostic **recs,
             xmlNodePtr rptr = xmlNewChild(pptr, ns_diag,
                                           BAD_CAST "diagnostic", 0);
             add_xsd_string(rptr, "uri", (*recs)[i].uri);
+            add_xsd_string(rptr, "details", (*recs)[i].details);
             if ((*recs)[i].message)
                 add_xsd_string(rptr, "message", (*recs)[i].message);
             else if ((*recs)[i].uri )
@@ -464,7 +478,6 @@ static int yaz_srw_diagnostics(ODR o, xmlNodePtr pptr, Z_SRW_diagnostic **recs,
                         add_xsd_string(rptr, "message", message);
                 }
             }
-            add_xsd_string(rptr, "details", (*recs)[i].details);
         }
     }
     return 0;
@@ -717,7 +730,7 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                 else if (yaz_match_xsd_element(ptr, "diagnostics"))
                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
                                         &res->num_diagnostics,
-                                        client_data, ns);
+                                        client_data, ns, 0);
                 else if (yaz_match_xsd_element(ptr, "facet_analysis"))
                     yaz_sru_proxy_decode_facets(o, ptr, &res->facetList);
                 else if (yaz_match_xsd_element(ptr, "facetedResults"))
@@ -785,7 +798,7 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                 else if (yaz_match_xsd_element(ptr, "diagnostics"))
                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
                                         &res->num_diagnostics,
-                                        client_data, ns);
+                                        client_data, ns, 0);
                 ;
             }
         }
@@ -863,7 +876,7 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                 else if (yaz_match_xsd_element(ptr, "diagnostics"))
                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
                                         &res->num_diagnostics,
-                                        client_data, ns);
+                                        client_data, ns, 0);
             }
         }
         else
@@ -892,11 +905,10 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
             xmlSetNs(ptr, ns_srw);
 
-            add_xsd_string(ptr, "version", (*p)->srw_version);
+            if (!version2)
+                add_xsd_string(ptr, "version", (*p)->srw_version);
             if (version2)
             {
-                if (queryType)
-                    add_xsd_string(ptr, "queryType", queryType);
                 add_xsd_string(ptr, "query", req->query);
             }
             else
@@ -907,19 +919,19 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                     add_xsd_string(ptr, "xQuery", req->query);
                 else if (!strcmp(queryType, "pqf"))
                     add_xsd_string(ptr, "pQuery", req->query);
+                queryType = 0;
             }
             add_xsd_integer(ptr, "startRecord", req->startRecord);
             add_xsd_integer(ptr, "maximumRecords", req->maximumRecords);
             if (version2)
-            {
                 add_xsd_string(ptr, "recordXMLEscaping", req->recordPacking);
-                add_xsd_string(ptr, "recordPacking", req->packing);
-            }
             else
                 add_xsd_string(ptr, "recordPacking", req->recordPacking);
             add_xsd_string(ptr, "recordSchema", req->recordSchema);
             add_xsd_string(ptr, "recordXPath", req->recordXPath);
             add_xsd_integer(ptr, "resultSetTTL", req->resultSetTTL);
+            add_xsd_string(ptr, "stylesheet", req->stylesheet);
+            add_xsd_string(ptr, "queryType", queryType);
             switch (req->sort_type)
             {
             case Z_SRW_sort_type_none:
@@ -931,8 +943,10 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                 add_xsd_string(ptr, "xSortKeys", req->sort.xSortKeys);
                 break;
             }
-            add_xsd_string(ptr, "stylesheet", req->stylesheet);
+            /* still unsupported are: renderedBy, httpAccept, responseType */
             add_xsd_string(ptr, "database", req->database);
+            if (version2)
+                add_xsd_string(ptr, "recordPacking", req->packing);
             {
                 const char *limit = 0;
                 const char *start = 0;
@@ -953,12 +967,13 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
             xmlSetNs(ptr, ns_srw);
 
-            add_xsd_string(ptr, "version", (*p)->srw_version);
+            if (!version2)
+                add_xsd_string(ptr, "version", (*p)->srw_version);
             add_xsd_integer(ptr, "numberOfRecords", res->numberOfRecords);
             add_xsd_string(ptr, "resultSetId", res->resultSetId);
-            add_xsd_integer(ptr,
-                            version2 ? "resultSetTTL" : "resultSetIdleTime" ,
-                            res->resultSetIdleTime);
+            if (!version2)
+                add_xsd_integer(ptr, "resultSetIdleTime",
+                                res->resultSetIdleTime);
             if (res->num_records)
             {
                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "records", 0);
@@ -973,21 +988,33 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
                                               0);
                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
-                                    &res->num_diagnostics, client_data, ns);
+                                    &res->num_diagnostics, client_data, ns,
+                                    version2);
             }
-            if (res->resultCountPrecision)
+            if (version2)
+            {
+                if (ptr && (*p)->extraResponseData_len)
+                    add_XML_n(ptr, "extraResponseData",
+                              (*p)->extraResponseData_buf,
+                              (*p)->extraResponseData_len, ns_srw);
+                add_xsd_integer(ptr, "resultSetTTL", res->resultSetIdleTime);
                 add_xsd_string(ptr, "resultCountPrecision",
                                res->resultCountPrecision);
-            yaz_sru_facet_response(o, &res->facetList, ptr);
+                yaz_sru_facet_response(o, &res->facetList, ptr);
+                return 0; /* so we don't make extra response data twice */
+            }
         }
         else if ((*p)->which == Z_SRW_explain_request)
         {
             Z_SRW_explainRequest *req = (*p)->u.explain_request;
+            if (version2)
+                ns = "http://docs.oasis-open.org/ns/search-ws/sruRequest";
             ptr = xmlNewChild(pptr, 0, BAD_CAST "explainRequest", 0);
             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
             xmlSetNs(ptr, ns_srw);
 
-            add_xsd_string(ptr, "version", (*p)->srw_version);
+            if (!version2)
+                add_xsd_string(ptr, "version", (*p)->srw_version);
             if (version2)
             {
                 add_xsd_string(ptr, "recordXMLEscaping", req->recordPacking);
@@ -1001,6 +1028,8 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
         else if ((*p)->which == Z_SRW_explain_response)
         {
             Z_SRW_explainResponse *res = (*p)->u.explain_response;
+            if (version2)
+                ns = "http://docs.oasis-open.org/ns/search-ws/sruResponse";
             ptr = xmlNewChild(pptr, 0, BAD_CAST "explainResponse", 0);
             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
             xmlSetNs(ptr, ns_srw);
@@ -1017,7 +1046,8 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
                                               0);
                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
-                                    &res->num_diagnostics, client_data, ns);
+                                    &res->num_diagnostics, client_data, ns,
+                                    version2);
             }
         }
         else if ((*p)->which == Z_SRW_scan_request)
@@ -1030,7 +1060,8 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
             xmlSetNs(ptr, ns_srw);
 
-            add_xsd_string(ptr, "version", (*p)->srw_version);
+            if (!version2)
+                add_xsd_string(ptr, "version", (*p)->srw_version);
 
             if (version2)
             {
@@ -1059,7 +1090,8 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
             xmlSetNs(ptr, ns_srw);
 
-            add_xsd_string(ptr, "version", (*p)->srw_version);
+            if (!version2)
+                add_xsd_string(ptr, "version", (*p)->srw_version);
             if (res->num_terms)
             {
                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "terms", 0);
@@ -1071,7 +1103,8 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
                                               0);
                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
-                                    &res->num_diagnostics, client_data, ns);
+                                    &res->num_diagnostics, client_data, ns,
+                                    version2);
             }
         }
         else
@@ -1207,7 +1240,7 @@ int yaz_ucp_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                 else if (yaz_match_xsd_element(ptr, "diagnostics"))
                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
                                         &res->num_diagnostics,
-                                        client_data, ns_ucp_str);
+                                        client_data, ns_ucp_str, 0);
             }
         }
         else if (!xmlStrcmp(method->name, BAD_CAST "explainUpdateRequest"))
@@ -1290,7 +1323,7 @@ int yaz_ucp_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                xmlNodePtr rptr = xmlNewChild(ptr, ns_diag, BAD_CAST "diagnostics", 0);
                yaz_srw_diagnostics(o, rptr, &res->diagnostics,
                                     &res->num_diagnostics, client_data,
-                                    ns_ucp_str);
+                                    ns_ucp_str, 0);
             }
            if (res->extraResponseData_len)
                 add_XML_n(ptr, "extraResponseData",