1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2011 Index Data
3 * See the file LICENSE for details.
7 * \brief Implements SRW/SRU package encoding and decoding
16 #include <yaz/wrbuf.h>
18 #include <libxml/parser.h>
19 #include <libxml/tree.h>
22 static void add_XML_n(xmlNodePtr ptr, const char *elem, char *val, int len,
27 xmlDocPtr doc = xmlParseMemory(val,len);
30 xmlNodePtr c = xmlNewChild(ptr, ns_ptr, BAD_CAST elem, 0);
31 xmlNodePtr t = xmlDocGetRootElement(doc);
32 xmlAddChild(c, xmlCopyNode(t,1));
38 xmlNodePtr add_xsd_string_n(xmlNodePtr ptr, const char *elem, const char *val,
43 xmlNodePtr c = xmlNewChild(ptr, 0, BAD_CAST elem, 0);
44 xmlNodePtr t = xmlNewTextLen(BAD_CAST val, len);
51 xmlNodePtr add_xsd_string_ns(xmlNodePtr ptr, const char *elem, const char *val,
56 xmlNodePtr c = xmlNewChild(ptr, ns_ptr, BAD_CAST elem, 0);
57 xmlNodePtr t = xmlNewText(BAD_CAST val);
64 xmlNodePtr add_xsd_string(xmlNodePtr ptr, const char *elem, const char *val)
66 return add_xsd_string_ns(ptr, elem, val, 0);
69 static void add_xsd_integer(xmlNodePtr ptr, const char *elem,
75 sprintf(str, ODR_INT_PRINTF, *val);
76 xmlNewTextChild(ptr, 0, BAD_CAST elem, BAD_CAST str);
80 static int match_element(xmlNodePtr ptr, const char *elem)
82 if (ptr->type == XML_ELEMENT_NODE && !xmlStrcmp(ptr->name, BAD_CAST elem))
91 static int match_xsd_string_n(xmlNodePtr ptr, const char *elem, ODR o,
95 struct _xmlAttr *attr;
97 if (!match_element(ptr, elem))
100 for (attr = ptr->properties; attr; attr = attr->next)
101 if (!strcmp(attr->name, "type") &&
102 attr->children && attr->children->type == XML_TEXT_NODE)
104 const char *t = strchr(attr->children->content, ':');
108 t = attr->children->content;
109 if (!strcmp(t, "string"))
116 if (!ptr || ptr->type != XML_TEXT_NODE)
121 *val = odr_strdup(o, (const char *) ptr->content);
123 *len = xmlStrlen(ptr->content);
128 static int match_xsd_string(xmlNodePtr ptr, const char *elem, ODR o,
131 return match_xsd_string_n(ptr, elem, o, val, 0);
134 static int match_xsd_XML_n(xmlNodePtr ptr, const char *elem, ODR o,
135 char **val, int *len)
139 if (!match_element(ptr, elem))
142 buf = xmlBufferCreate();
144 /* Copy each element nodes at top.
145 In most cases there is only one root node.. At least one server
146 http://www.theeuropeanlibrary.org/sru/sru.pl
147 has multiple root nodes in recordData.
149 for (ptr = ptr->children; ptr; ptr = ptr->next)
151 if (ptr->type == XML_ELEMENT_NODE)
153 /* copy node to get NS right (bug #740). */
154 xmlNode *tmp = xmlCopyNode(ptr, 1);
156 xmlNodeDump(buf, tmp->doc, tmp, 0, 0);
162 *val = (char *) odr_malloc(o, buf->use+1);
163 memcpy (*val, buf->content, buf->use);
164 (*val)[buf->use] = '\0';
174 static int match_xsd_integer(xmlNodePtr ptr, const char *elem, ODR o,
178 struct _xmlAttr *attr;
180 if (!match_element(ptr, elem))
183 for (attr = ptr->properties; attr; attr = attr->next)
184 if (!strcmp(attr->name, "type") &&
185 attr->children && attr->children->type == XML_TEXT_NODE)
187 const char *t = strchr(attr->children->content, ':');
191 t = attr->children->content;
192 if (!strcmp(t, "integer"))
199 if (!ptr || ptr->type != XML_TEXT_NODE)
201 *val = odr_intdup(o, odr_atoi((const char *) ptr->content));
205 char *yaz_negotiate_sru_version(char *input_ver)
210 if (!strcmp(input_ver, "1.1"))
212 return "1.2"; /* our latest supported version */
215 static int yaz_srw_record(ODR o, xmlNodePtr pptr, Z_SRW_record *rec,
216 Z_SRW_extra_record **extra,
217 void *client_data, const char *ns)
219 if (o->direction == ODR_DECODE)
221 Z_SRW_extra_record ex;
224 int pack = Z_SRW_recordPacking_string;
226 xmlNodePtr data_ptr = 0;
227 rec->recordSchema = 0;
228 rec->recordData_buf = 0;
229 rec->recordData_len = 0;
230 rec->recordPosition = 0;
233 ex.extraRecordData_buf = 0;
234 ex.extraRecordData_len = 0;
235 ex.recordIdentifier = 0;
237 for (ptr = pptr->children; ptr; ptr = ptr->next)
240 if (match_xsd_string(ptr, "recordSchema", o,
243 else if (match_xsd_string(ptr, "recordPacking", o, &spack))
246 pack = yaz_srw_str_to_pack(spack);
248 else if (match_xsd_integer(ptr, "recordPosition", o,
249 &rec->recordPosition))
251 else if (match_element(ptr, "recordData"))
253 /* save position of Data until after the loop
254 then we will know the packing (hopefully), and
255 unpacking is done once
259 else if (match_xsd_XML_n(ptr, "extraRecordData", o,
260 &ex.extraRecordData_buf,
261 &ex.extraRecordData_len) )
263 else if (match_xsd_string(ptr, "recordIdentifier", o,
264 &ex.recordIdentifier))
272 case Z_SRW_recordPacking_XML:
273 match_xsd_XML_n(data_ptr, "recordData", o,
274 &rec->recordData_buf, &rec->recordData_len);
276 case Z_SRW_recordPacking_URL:
277 /* just store it as a string.
278 leave it to the backend to collect the document */
279 match_xsd_string_n(data_ptr, "recordData", o,
280 &rec->recordData_buf, &rec->recordData_len);
282 case Z_SRW_recordPacking_string:
283 match_xsd_string_n(data_ptr, "recordData", o,
284 &rec->recordData_buf, &rec->recordData_len);
288 rec->recordPacking = pack;
289 if (ex.extraRecordData_buf || ex.recordIdentifier)
291 *extra = (Z_SRW_extra_record *)
292 odr_malloc(o, sizeof(Z_SRW_extra_record));
293 memcpy(*extra, &ex, sizeof(Z_SRW_extra_record));
296 else if (o->direction == ODR_ENCODE)
298 xmlNodePtr ptr = pptr;
299 int pack = rec->recordPacking;
300 const char *spack = yaz_srw_pack_to_str(pack);
302 add_xsd_string(ptr, "recordSchema", rec->recordSchema);
304 add_xsd_string(ptr, "recordPacking", spack);
307 case Z_SRW_recordPacking_string:
308 add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
309 rec->recordData_len);
311 case Z_SRW_recordPacking_XML:
312 add_XML_n(ptr, "recordData", rec->recordData_buf,
313 rec->recordData_len, 0);
315 case Z_SRW_recordPacking_URL:
316 add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
317 rec->recordData_len);
320 if (rec->recordPosition)
321 add_xsd_integer(ptr, "recordPosition", rec->recordPosition );
324 if ((*extra)->recordIdentifier)
325 add_xsd_string(ptr, "recordIdentifier",
326 (*extra)->recordIdentifier);
327 if ((*extra)->extraRecordData_buf)
328 add_XML_n(ptr, "extraRecordData",
329 (*extra)->extraRecordData_buf,
330 (*extra)->extraRecordData_len, 0);
336 static int yaz_srw_records(ODR o, xmlNodePtr pptr, Z_SRW_record **recs,
337 Z_SRW_extra_record ***extra,
338 int *num, void *client_data, const char *ns)
340 if (o->direction == ODR_DECODE)
345 for (ptr = pptr->children; ptr; ptr = ptr->next)
347 if (ptr->type == XML_ELEMENT_NODE &&
348 !xmlStrcmp(ptr->name, BAD_CAST "record"))
353 *recs = (Z_SRW_record *) odr_malloc(o, *num * sizeof(**recs));
354 *extra = (Z_SRW_extra_record **) odr_malloc(o, *num * sizeof(**extra));
355 for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next)
357 if (ptr->type == XML_ELEMENT_NODE &&
358 !xmlStrcmp(ptr->name, BAD_CAST "record"))
360 yaz_srw_record(o, ptr, *recs + i, *extra + i, client_data, ns);
365 else if (o->direction == ODR_ENCODE)
368 for (i = 0; i < *num; i++)
370 xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "record",
372 yaz_srw_record(o, rptr, (*recs)+i, (*extra ? *extra + i : 0),
379 static int yaz_srw_version(ODR o, xmlNodePtr pptr, Z_SRW_recordVersion *rec,
380 void *client_data, const char *ns)
382 if (o->direction == ODR_DECODE)
385 rec->versionType = 0;
386 rec->versionValue = 0;
387 for (ptr = pptr->children; ptr; ptr = ptr->next)
390 if (match_xsd_string(ptr, "versionType", o,
393 else if (match_xsd_string(ptr, "versionValue", o,
398 else if (o->direction == ODR_ENCODE)
400 xmlNodePtr ptr = pptr;
401 add_xsd_string(ptr, "versionType", rec->versionType);
402 add_xsd_string(ptr, "versionValue", rec->versionValue);
407 static int yaz_srw_versions(ODR o, xmlNodePtr pptr,
408 Z_SRW_recordVersion **vers,
409 int *num, void *client_data, const char *ns)
411 if (o->direction == ODR_DECODE)
416 for (ptr = pptr->children; ptr; ptr = ptr->next)
418 if (ptr->type == XML_ELEMENT_NODE &&
419 !xmlStrcmp(ptr->name, BAD_CAST "recordVersion"))
424 *vers = (Z_SRW_recordVersion *) odr_malloc(o, *num * sizeof(**vers));
425 for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next)
427 if (ptr->type == XML_ELEMENT_NODE &&
428 !xmlStrcmp(ptr->name, BAD_CAST "recordVersion"))
430 yaz_srw_version(o, ptr, *vers + i, client_data, ns);
435 else if (o->direction == ODR_ENCODE)
438 for (i = 0; i < *num; i++)
440 xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "version",
442 yaz_srw_version(o, rptr, (*vers)+i, client_data, ns);
448 Z_FacetTerm *yaz_sru_proxy_get_facet_term_count(ODR odr, xmlNodePtr node) {
452 WRBUF wrbuf = wrbuf_alloc();
453 const char *freq_string = yaz_element_attribute_value_get(node, "facetvalue", "est_representation");
456 freq = atoi(freq_string);
460 for (child = node->children; child ; child = child->next) {
461 if (child->type == XML_TEXT_NODE)
462 wrbuf_puts(wrbuf, (const char *) child->content);
464 term = term_create(odr, wrbuf_cstr(wrbuf));
465 yaz_log(YLOG_DEBUG, "sru-proxy facet: %s %d", wrbuf_cstr(wrbuf), freq);
466 wrbuf_destroy(wrbuf);
467 return facet_term_create(odr, term, freq);
470 static Z_FacetField *yaz_sru_proxy_decode_facet_field(ODR odr, xmlNodePtr ptr) {
471 Z_AttributeList *list;
472 Z_FacetField *facet_field;
477 const char* name = yaz_element_attribute_value_get(ptr, "facet", "code");
478 yaz_log(YLOG_DEBUG, "sru-proxy facet type: %s", name);
480 list = yaz_use_atttribute_create(odr, name);
481 for (node = ptr->children; node; node = node->next) {
482 if (match_element(node, "facetvalue"))
485 facet_field = facet_field_create(odr, list, num_terms);
487 for (node = ptr->children; node; node = node->next) {
488 if (match_element(node, "facetvalue")) {
489 facet_field_term_set(odr, facet_field, yaz_sru_proxy_get_facet_term_count(odr, node), index);
496 static int yaz_sru_proxy_decode_facets(ODR o, xmlNodePtr root, Z_FacetList **facetList)
500 for (ptr = root->children; ptr; ptr = ptr->next)
502 if (match_element(ptr, "facets"))
505 Z_FacetList *facet_list;
507 for (node = ptr->children; node; node= node->next)
509 if (node->type == XML_ELEMENT_NODE)
512 facet_list = facet_list_create(o, num_facets);
514 for (node = ptr->children; node; node= node->next)
516 if (match_element(node, "facet")) {
517 facet_list_field_set(o, facet_list, yaz_sru_proxy_decode_facet_field(o, node), num_facets);
521 *facetList = facet_list;
530 static int yaz_srw_decode_diagnostics(ODR o, xmlNodePtr pptr,
531 Z_SRW_diagnostic **recs, int *num,
532 void *client_data, const char *ns)
537 for (ptr = pptr; ptr; ptr = ptr->next)
539 if (ptr->type == XML_ELEMENT_NODE &&
540 !xmlStrcmp(ptr->name, BAD_CAST "diagnostic"))
545 *recs = (Z_SRW_diagnostic *) odr_malloc(o, *num * sizeof(**recs));
546 for (i = 0; i < *num; i++)
549 (*recs)[i].details = 0;
550 (*recs)[i].message = 0;
552 for (i = 0, ptr = pptr; ptr; ptr = ptr->next)
554 if (ptr->type == XML_ELEMENT_NODE &&
555 !xmlStrcmp(ptr->name, BAD_CAST "diagnostic"))
559 (*recs)[i].details = 0;
560 (*recs)[i].message = 0;
561 for (rptr = ptr->children; rptr; rptr = rptr->next)
563 if (match_xsd_string(rptr, "uri", o,
566 else if (match_xsd_string(rptr, "details", o,
567 &(*recs)[i].details))
569 else if (match_xsd_string(rptr, "message", o,
570 &(*recs)[i].message))
579 int sru_decode_surrogate_diagnostics(const char *buf, size_t len,
580 Z_SRW_diagnostic **diag,
584 xmlDocPtr doc = xmlParseMemory(buf, len);
587 xmlNodePtr ptr = xmlDocGetRootElement(doc);
588 while (ptr && ptr->type != XML_ELEMENT_NODE)
591 && !xmlStrcmp(ptr->ns->href,
592 BAD_CAST "http://www.loc.gov/zing/srw/diagnostic/"))
594 ret = yaz_srw_decode_diagnostics(odr, ptr, diag, num, 0, 0);
601 static int yaz_srw_diagnostics(ODR o, xmlNodePtr pptr, Z_SRW_diagnostic **recs,
602 int *num, void *client_data, const char *ns)
604 if (o->direction == ODR_DECODE)
606 return yaz_srw_decode_diagnostics(o, pptr->children, recs, num, client_data, ns);
608 else if (o->direction == ODR_ENCODE)
612 xmlNewNs(pptr, BAD_CAST YAZ_XMLNS_DIAG_v1_1, BAD_CAST "diag" );
613 for (i = 0; i < *num; i++)
615 const char *std_diag = "info:srw/diagnostic/1/";
616 const char *ucp_diag = "info:srw/diagnostic/12/";
617 xmlNodePtr rptr = xmlNewChild(pptr, ns_diag,
618 BAD_CAST "diagnostic", 0);
619 add_xsd_string(rptr, "uri", (*recs)[i].uri);
620 if ((*recs)[i].message)
621 add_xsd_string(rptr, "message", (*recs)[i].message);
622 else if ((*recs)[i].uri )
624 if (!strncmp((*recs)[i].uri, std_diag, strlen(std_diag)))
626 int no = atoi((*recs)[i].uri + strlen(std_diag));
627 const char *message = yaz_diag_srw_str(no);
629 add_xsd_string(rptr, "message", message);
631 else if (!strncmp((*recs)[i].uri, ucp_diag, strlen(ucp_diag)))
633 int no = atoi((*recs)[i].uri + strlen(ucp_diag));
634 const char *message = yaz_diag_sru_update_str(no);
636 add_xsd_string(rptr, "message", message);
639 add_xsd_string(rptr, "details", (*recs)[i].details);
645 static int yaz_srw_term(ODR o, xmlNodePtr pptr, Z_SRW_scanTerm *term,
646 void *client_data, const char *ns)
648 if (o->direction == ODR_DECODE)
652 term->numberOfRecords = 0;
653 term->displayTerm = 0;
654 term->whereInList = 0;
655 for (ptr = pptr->children; ptr; ptr = ptr->next)
657 if (match_xsd_string(ptr, "value", o, &term->value))
659 else if (match_xsd_integer(ptr, "numberOfRecords", o,
660 &term->numberOfRecords))
662 else if (match_xsd_string(ptr, "displayTerm", o,
665 else if (match_xsd_string(ptr, "whereInList", o,
670 else if (o->direction == ODR_ENCODE)
672 xmlNodePtr ptr = pptr;
673 add_xsd_string(ptr, "value", term->value);
674 add_xsd_integer(ptr, "numberOfRecords", term->numberOfRecords);
675 add_xsd_string(ptr, "displayTerm", term->displayTerm);
676 add_xsd_string(ptr, "whereInList", term->whereInList);
681 static int yaz_srw_terms(ODR o, xmlNodePtr pptr, Z_SRW_scanTerm **terms,
682 int *num, void *client_data, const char *ns)
684 if (o->direction == ODR_DECODE)
689 for (ptr = pptr->children; ptr; ptr = ptr->next)
691 if (ptr->type == XML_ELEMENT_NODE &&
692 !xmlStrcmp(ptr->name, BAD_CAST "term"))
697 *terms = (Z_SRW_scanTerm *) odr_malloc(o, *num * sizeof(**terms));
698 for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next, i++)
700 if (ptr->type == XML_ELEMENT_NODE &&
701 !xmlStrcmp(ptr->name, BAD_CAST "term"))
702 yaz_srw_term(o, ptr, (*terms)+i, client_data, ns);
705 else if (o->direction == ODR_ENCODE)
708 for (i = 0; i < *num; i++)
710 xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "term", 0);
711 yaz_srw_term(o, rptr, (*terms)+i, client_data, ns);
717 int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
718 void *client_data, const char *ns)
720 xmlNodePtr pptr = (xmlNodePtr) vptr;
721 if (o->direction == ODR_DECODE)
723 Z_SRW_PDU **p = handler_data;
724 xmlNodePtr method = pptr->children;
727 while (method && method->type == XML_TEXT_NODE)
728 method = method->next;
732 if (method->type != XML_ELEMENT_NODE)
735 *p = yaz_srw_get_core_v_1_1(o);
737 if (!xmlStrcmp(method->name, BAD_CAST "searchRetrieveRequest"))
739 xmlNodePtr ptr = method->children;
740 Z_SRW_searchRetrieveRequest *req;
742 (*p)->which = Z_SRW_searchRetrieve_request;
743 req = (*p)->u.request = (Z_SRW_searchRetrieveRequest *)
744 odr_malloc(o, sizeof(*req));
745 req->query_type = Z_SRW_query_type_cql;
747 req->sort_type = Z_SRW_sort_type_none;
749 req->startRecord = 0;
750 req->maximumRecords = 0;
751 req->recordSchema = 0;
752 req->recordPacking = 0;
753 req->recordXPath = 0;
754 req->resultSetTTL = 0;
758 for (; ptr; ptr = ptr->next)
760 if (match_xsd_string(ptr, "version", o,
763 else if (match_xsd_string(ptr, "query", o,
765 req->query_type = Z_SRW_query_type_cql;
766 else if (match_xsd_string(ptr, "pQuery", o,
768 req->query_type = Z_SRW_query_type_pqf;
769 else if (match_xsd_string(ptr, "xQuery", o,
771 req->query_type = Z_SRW_query_type_xcql;
772 else if (match_xsd_integer(ptr, "startRecord", o,
775 else if (match_xsd_integer(ptr, "maximumRecords", o,
776 &req->maximumRecords))
778 else if (match_xsd_string(ptr, "recordPacking", o,
779 &req->recordPacking))
781 else if (match_xsd_string(ptr, "recordSchema", o,
784 else if (match_xsd_string(ptr, "recordXPath", o,
787 else if (match_xsd_integer(ptr, "resultSetTTL", o,
790 else if (match_xsd_string(ptr, "sortKeys", o,
791 &req->sort.sortKeys))
792 req->sort_type = Z_SRW_sort_type_sort;
793 else if (match_xsd_string(ptr, "stylesheet", o,
796 else if (match_xsd_string(ptr, "database", o,
800 if (!req->query.cql && !req->query.pqf && !req->query.xcql)
802 /* should put proper diagnostic here */
806 else if (!xmlStrcmp(method->name, BAD_CAST "searchRetrieveResponse"))
808 xmlNodePtr ptr = method->children;
809 Z_SRW_searchRetrieveResponse *res;
811 (*p)->which = Z_SRW_searchRetrieve_response;
812 res = (*p)->u.response = (Z_SRW_searchRetrieveResponse *)
813 odr_malloc(o, sizeof(*res));
815 res->numberOfRecords = 0;
816 res->resultSetId = 0;
817 res->resultSetIdleTime = 0;
819 res->num_records = 0;
820 res->diagnostics = 0;
821 res->num_diagnostics = 0;
822 res->nextRecordPosition = 0;
825 for (; ptr; ptr = ptr->next)
827 if (match_xsd_string(ptr, "version", o,
830 else if (match_xsd_XML_n(ptr, "extraResponseData", o,
831 &(*p)->extraResponseData_buf,
832 &(*p)->extraResponseData_len))
834 else if (match_xsd_integer(ptr, "numberOfRecords", o,
835 &res->numberOfRecords))
837 else if (match_xsd_string(ptr, "resultSetId", o,
840 else if (match_xsd_integer(ptr, "resultSetIdleTime", o,
841 &res->resultSetIdleTime))
843 else if (match_element(ptr, "records"))
844 yaz_srw_records(o, ptr, &res->records,
846 &res->num_records, client_data, ns);
847 else if (match_xsd_integer(ptr, "nextRecordPosition", o,
848 &res->nextRecordPosition))
850 else if (match_element(ptr, "diagnostics"))
851 yaz_srw_diagnostics(o, ptr, &res->diagnostics,
852 &res->num_diagnostics,
854 else if (match_element(ptr, "facet_analysis"))
855 yaz_sru_proxy_decode_facets(o, ptr, &res->facetList);
858 else if (!xmlStrcmp(method->name, BAD_CAST "explainRequest"))
860 Z_SRW_explainRequest *req;
861 xmlNodePtr ptr = method->children;
863 (*p)->which = Z_SRW_explain_request;
864 req = (*p)->u.explain_request = (Z_SRW_explainRequest *)
865 odr_malloc(o, sizeof(*req));
866 req->recordPacking = 0;
869 for (; ptr; ptr = ptr->next)
871 if (match_xsd_string(ptr, "version", o,
874 else if (match_xsd_XML_n(ptr, "extraResponseData", o,
875 &(*p)->extraResponseData_buf,
876 &(*p)->extraResponseData_len))
878 else if (match_xsd_string(ptr, "stylesheet", o,
881 else if (match_xsd_string(ptr, "recordPacking", o,
882 &req->recordPacking))
884 else if (match_xsd_string(ptr, "database", o,
889 else if (!xmlStrcmp(method->name, BAD_CAST "explainResponse"))
891 Z_SRW_explainResponse *res;
892 xmlNodePtr ptr = method->children;
894 (*p)->which = Z_SRW_explain_response;
895 res = (*p)->u.explain_response = (Z_SRW_explainResponse*)
896 odr_malloc(o, sizeof(*res));
897 res->diagnostics = 0;
898 res->num_diagnostics = 0;
899 res->record.recordSchema = 0;
900 res->record.recordData_buf = 0;
901 res->record.recordData_len = 0;
902 res->record.recordPosition = 0;
904 for (; ptr; ptr = ptr->next)
906 if (match_xsd_string(ptr, "version", o,
909 else if (match_xsd_XML_n(ptr, "extraResponseData", o,
910 &(*p)->extraResponseData_buf,
911 &(*p)->extraResponseData_len))
913 else if (match_element(ptr, "record"))
914 yaz_srw_record(o, ptr, &res->record, &res->extra_record,
916 else if (match_element(ptr, "diagnostics"))
917 yaz_srw_diagnostics(o, ptr, &res->diagnostics,
918 &res->num_diagnostics,
923 else if (!xmlStrcmp(method->name, BAD_CAST "scanRequest"))
925 Z_SRW_scanRequest *req;
926 xmlNodePtr ptr = method->children;
928 (*p)->which = Z_SRW_scan_request;
929 req = (*p)->u.scan_request = (Z_SRW_scanRequest *)
930 odr_malloc(o, sizeof(*req));
931 req->query_type = Z_SRW_query_type_cql;
932 req->scanClause.cql = 0;
933 req->responsePosition = 0;
934 req->maximumTerms = 0;
938 for (; ptr; ptr = ptr->next)
940 if (match_xsd_string(ptr, "version", o,
943 else if (match_xsd_XML_n(ptr, "extraResponseData", o,
944 &(*p)->extraResponseData_buf,
945 &(*p)->extraResponseData_len))
947 else if (match_xsd_string(ptr, "scanClause", o,
948 &req->scanClause.cql))
950 else if (match_xsd_string(ptr, "pScanClause", o,
951 &req->scanClause.pqf))
953 req->query_type = Z_SRW_query_type_pqf;
955 else if (match_xsd_integer(ptr, "responsePosition", o,
956 &req->responsePosition))
958 else if (match_xsd_integer(ptr, "maximumTerms", o,
961 else if (match_xsd_string(ptr, "stylesheet", o,
964 else if (match_xsd_string(ptr, "database", o,
969 else if (!xmlStrcmp(method->name, BAD_CAST "scanResponse"))
971 Z_SRW_scanResponse *res;
972 xmlNodePtr ptr = method->children;
974 (*p)->which = Z_SRW_scan_response;
975 res = (*p)->u.scan_response = (Z_SRW_scanResponse *)
976 odr_malloc(o, sizeof(*res));
979 res->diagnostics = 0;
980 res->num_diagnostics = 0;
982 for (; ptr; ptr = ptr->next)
984 if (match_xsd_string(ptr, "version", o,
987 else if (match_xsd_XML_n(ptr, "extraResponseData", o,
988 &(*p)->extraResponseData_buf,
989 &(*p)->extraResponseData_len))
991 else if (match_element(ptr, "terms"))
992 yaz_srw_terms(o, ptr, &res->terms,
993 &res->num_terms, client_data,
995 else if (match_element(ptr, "diagnostics"))
996 yaz_srw_diagnostics(o, ptr, &res->diagnostics,
997 &res->num_diagnostics,
1006 neg_version = yaz_negotiate_sru_version((*p)->srw_version);
1008 (*p)->srw_version = neg_version;
1010 else if (o->direction == ODR_ENCODE)
1012 Z_SRW_PDU **p = handler_data;
1016 if ((*p)->which == Z_SRW_searchRetrieve_request)
1018 Z_SRW_searchRetrieveRequest *req = (*p)->u.request;
1019 ptr = xmlNewChild(pptr, 0, BAD_CAST "searchRetrieveRequest", 0);
1020 ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1021 xmlSetNs(ptr, ns_srw);
1023 if ((*p)->srw_version)
1024 add_xsd_string(ptr, "version", (*p)->srw_version);
1025 switch(req->query_type)
1027 case Z_SRW_query_type_cql:
1028 add_xsd_string(ptr, "query", req->query.cql);
1030 case Z_SRW_query_type_xcql:
1031 add_xsd_string(ptr, "xQuery", req->query.xcql);
1033 case Z_SRW_query_type_pqf:
1034 add_xsd_string(ptr, "pQuery", req->query.pqf);
1037 add_xsd_integer(ptr, "startRecord", req->startRecord);
1038 add_xsd_integer(ptr, "maximumRecords", req->maximumRecords);
1039 add_xsd_string(ptr, "recordPacking", req->recordPacking);
1040 add_xsd_string(ptr, "recordSchema", req->recordSchema);
1041 add_xsd_string(ptr, "recordXPath", req->recordXPath);
1042 add_xsd_integer(ptr, "resultSetTTL", req->resultSetTTL);
1043 switch(req->sort_type)
1045 case Z_SRW_sort_type_none:
1047 case Z_SRW_sort_type_sort:
1048 add_xsd_string(ptr, "sortKeys", req->sort.sortKeys);
1050 case Z_SRW_sort_type_xSort:
1051 add_xsd_string(ptr, "xSortKeys", req->sort.xSortKeys);
1054 add_xsd_string(ptr, "stylesheet", req->stylesheet);
1055 add_xsd_string(ptr, "database", req->database);
1057 else if ((*p)->which == Z_SRW_searchRetrieve_response)
1059 Z_SRW_searchRetrieveResponse *res = (*p)->u.response;
1060 ptr = xmlNewChild(pptr, 0, BAD_CAST "searchRetrieveResponse", 0);
1061 ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1062 xmlSetNs(ptr, ns_srw);
1064 if ((*p)->srw_version)
1065 add_xsd_string(ptr, "version", (*p)->srw_version);
1066 add_xsd_integer(ptr, "numberOfRecords", res->numberOfRecords);
1067 add_xsd_string(ptr, "resultSetId", res->resultSetId);
1068 add_xsd_integer(ptr, "resultSetIdleTime", res->resultSetIdleTime);
1069 if (res->num_records)
1071 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "records", 0);
1072 yaz_srw_records(o, rptr, &res->records, &res->extra_records,
1076 add_xsd_integer(ptr, "nextRecordPosition",
1077 res->nextRecordPosition);
1078 if (res->num_diagnostics)
1080 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
1082 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1083 &res->num_diagnostics, client_data, ns);
1086 else if ((*p)->which == Z_SRW_explain_request)
1088 Z_SRW_explainRequest *req = (*p)->u.explain_request;
1089 ptr = xmlNewChild(pptr, 0, BAD_CAST "explainRequest", 0);
1090 ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1091 xmlSetNs(ptr, ns_srw);
1093 add_xsd_string(ptr, "version", (*p)->srw_version);
1094 add_xsd_string(ptr, "recordPacking", req->recordPacking);
1095 add_xsd_string(ptr, "stylesheet", req->stylesheet);
1096 add_xsd_string(ptr, "database", req->database);
1098 else if ((*p)->which == Z_SRW_explain_response)
1100 Z_SRW_explainResponse *res = (*p)->u.explain_response;
1101 ptr = xmlNewChild(pptr, 0, BAD_CAST "explainResponse", 0);
1102 ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1103 xmlSetNs(ptr, ns_srw);
1105 add_xsd_string(ptr, "version", (*p)->srw_version);
1108 xmlNodePtr ptr1 = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
1109 yaz_srw_record(o, ptr1, &res->record, &res->extra_record,
1112 if (res->num_diagnostics)
1114 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
1116 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1117 &res->num_diagnostics, client_data, ns);
1120 else if ((*p)->which == Z_SRW_scan_request)
1122 Z_SRW_scanRequest *req = (*p)->u.scan_request;
1123 ptr = xmlNewChild(pptr, 0, BAD_CAST "scanRequest", 0);
1124 ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1125 xmlSetNs(ptr, ns_srw);
1127 add_xsd_string(ptr, "version", (*p)->srw_version);
1128 switch(req->query_type)
1130 case Z_SRW_query_type_cql:
1131 add_xsd_string(ptr, "scanClause", req->scanClause.cql);
1133 case Z_SRW_query_type_pqf:
1134 add_xsd_string(ptr, "pScanClause", req->scanClause.pqf);
1137 add_xsd_integer(ptr, "responsePosition", req->responsePosition);
1138 add_xsd_integer(ptr, "maximumTerms", req->maximumTerms);
1139 add_xsd_string(ptr, "stylesheet", req->stylesheet);
1140 add_xsd_string(ptr, "database", req->database);
1142 else if ((*p)->which == Z_SRW_scan_response)
1144 Z_SRW_scanResponse *res = (*p)->u.scan_response;
1145 ptr = xmlNewChild(pptr, 0, BAD_CAST "scanResponse", 0);
1146 ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1147 xmlSetNs(ptr, ns_srw);
1149 add_xsd_string(ptr, "version", (*p)->srw_version);
1153 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "terms", 0);
1154 yaz_srw_terms(o, rptr, &res->terms, &res->num_terms,
1157 if (res->num_diagnostics)
1159 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
1161 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1162 &res->num_diagnostics, client_data, ns);
1167 if (ptr && (*p)->extraResponseData_len)
1168 add_XML_n(ptr, "extraResponseData",
1169 (*p)->extraResponseData_buf,
1170 (*p)->extraResponseData_len, ns_srw);
1177 int yaz_ucp_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
1178 void *client_data, const char *ns_ucp_str)
1180 xmlNodePtr pptr = (xmlNodePtr) vptr;
1181 const char *ns_srw_str = YAZ_XMLNS_SRU_v1_1;
1182 if (o->direction == ODR_DECODE)
1184 Z_SRW_PDU **p = handler_data;
1185 xmlNodePtr method = pptr->children;
1187 while (method && method->type == XML_TEXT_NODE)
1188 method = method->next;
1192 if (method->type != XML_ELEMENT_NODE)
1195 *p = yaz_srw_get_core_v_1_1(o);
1197 if (!xmlStrcmp(method->name, BAD_CAST "updateRequest"))
1199 xmlNodePtr ptr = method->children;
1200 Z_SRW_updateRequest *req;
1203 (*p)->which = Z_SRW_update_request;
1204 req = (*p)->u.update_request = (Z_SRW_updateRequest *)
1205 odr_malloc(o, sizeof(*req));
1209 req->recordVersions = 0;
1210 req->num_recordVersions = 0;
1212 req->extra_record = 0;
1213 req->extraRequestData_buf = 0;
1214 req->extraRequestData_len = 0;
1215 req->stylesheet = 0;
1217 for (; ptr; ptr = ptr->next)
1219 if (match_xsd_string(ptr, "version", o,
1220 &(*p)->srw_version))
1222 else if (match_xsd_string(ptr, "action", o,
1225 if ( !strcmp(oper, "info:srw/action/1/delete"))
1226 req->operation = "delete";
1227 else if (!strcmp(oper,"info:srw/action/1/replace" ))
1228 req->operation = "replace";
1229 else if ( !strcmp( oper, "info:srw/action/1/create"))
1230 req->operation = "insert";
1233 else if (match_xsd_string(ptr, "recordIdentifier", o,
1236 else if (match_element(ptr, "recordVersions" ) )
1237 yaz_srw_versions( o, ptr, &req->recordVersions,
1238 &req->num_recordVersions, client_data,
1240 else if (match_element(ptr, "record"))
1242 req->record = yaz_srw_get_record(o);
1243 yaz_srw_record(o, ptr, req->record, &req->extra_record,
1244 client_data, ns_ucp_str);
1246 else if (match_xsd_string(ptr, "stylesheet", o,
1249 else if (match_xsd_string(ptr, "database", o,
1254 else if (!xmlStrcmp(method->name, BAD_CAST "updateResponse"))
1256 xmlNodePtr ptr = method->children;
1257 Z_SRW_updateResponse *res;
1259 (*p)->which = Z_SRW_update_response;
1260 res = (*p)->u.update_response = (Z_SRW_updateResponse *)
1261 odr_malloc(o, sizeof(*res));
1263 res->operationStatus = 0;
1265 res->recordVersions = 0;
1266 res->num_recordVersions = 0;
1267 res->diagnostics = 0;
1268 res->num_diagnostics = 0;
1270 res->extra_record = 0;
1271 res->extraResponseData_buf = 0;
1272 res->extraResponseData_len = 0;
1274 for (; ptr; ptr = ptr->next)
1276 if (match_xsd_string(ptr, "version", o,
1277 &(*p)->srw_version))
1279 else if (match_xsd_string(ptr, "operationStatus", o,
1280 &res->operationStatus ))
1282 else if (match_xsd_string(ptr, "recordIdentifier", o,
1285 else if (match_element(ptr, "recordVersions" ))
1286 yaz_srw_versions(o, ptr, &res->recordVersions,
1287 &res->num_recordVersions,
1288 client_data, ns_ucp_str);
1289 else if (match_element(ptr, "record"))
1291 res->record = yaz_srw_get_record(o);
1292 yaz_srw_record(o, ptr, res->record, &res->extra_record,
1293 client_data, ns_ucp_str);
1295 else if (match_element(ptr, "diagnostics"))
1296 yaz_srw_diagnostics(o, ptr, &res->diagnostics,
1297 &res->num_diagnostics,
1298 client_data, ns_ucp_str);
1301 else if (!xmlStrcmp(method->name, BAD_CAST "explainUpdateRequest"))
1304 else if (!xmlStrcmp(method->name, BAD_CAST "explainUpdateResponse"))
1313 else if (o->direction == ODR_ENCODE)
1315 Z_SRW_PDU **p = handler_data;
1316 xmlNsPtr ns_ucp, ns_srw;
1319 if ((*p)->which == Z_SRW_update_request)
1321 Z_SRW_updateRequest *req = (*p)->u.update_request;
1322 xmlNodePtr ptr = xmlNewChild(pptr, 0, BAD_CAST "updateRequest", 0);
1323 ns_ucp = xmlNewNs(ptr, BAD_CAST ns_ucp_str, BAD_CAST "zu");
1324 xmlSetNs(ptr, ns_ucp);
1325 ns_srw = xmlNewNs(ptr, BAD_CAST ns_srw_str, BAD_CAST "zs");
1327 add_xsd_string_ns(ptr, "version", (*p)->srw_version, ns_srw);
1328 add_xsd_string(ptr, "action", req->operation);
1329 add_xsd_string(ptr, "recordIdentifier", req->recordId );
1330 if (req->recordVersions)
1331 yaz_srw_versions( o, ptr, &req->recordVersions,
1332 &req->num_recordVersions,
1333 client_data, ns_ucp_str);
1334 if (req->record && req->record->recordData_len)
1336 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
1337 xmlSetNs(rptr, ns_srw);
1338 yaz_srw_record(o, rptr, req->record, &req->extra_record,
1339 client_data, ns_ucp_str);
1341 if (req->extraRequestData_len)
1343 add_XML_n(ptr, "extraRequestData",
1344 req->extraRequestData_buf,
1345 req->extraRequestData_len, ns_srw);
1347 add_xsd_string(ptr, "stylesheet", req->stylesheet);
1348 add_xsd_string(ptr, "database", req->database);
1350 else if ((*p)->which == Z_SRW_update_response)
1352 Z_SRW_updateResponse *res = (*p)->u.update_response;
1353 xmlNodePtr ptr = xmlNewChild(pptr, 0, (xmlChar *)
1354 "updateResponse", 0);
1355 ns_ucp = xmlNewNs(ptr, BAD_CAST ns_ucp_str, BAD_CAST "zu");
1356 xmlSetNs(ptr, ns_ucp);
1357 ns_srw = xmlNewNs(ptr, BAD_CAST ns_srw_str, BAD_CAST "zs");
1359 add_xsd_string_ns(ptr, "version", (*p)->srw_version, ns_srw);
1360 add_xsd_string(ptr, "operationStatus", res->operationStatus );
1361 add_xsd_string(ptr, "recordIdentifier", res->recordId );
1362 if (res->recordVersions)
1363 yaz_srw_versions(o, ptr, &res->recordVersions,
1364 &res->num_recordVersions,
1365 client_data, ns_ucp_str);
1366 if (res->record && res->record->recordData_len)
1368 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
1369 xmlSetNs(rptr, ns_srw);
1370 yaz_srw_record(o, rptr, res->record, &res->extra_record,
1371 client_data, ns_ucp_str);
1373 if (res->num_diagnostics)
1376 xmlNewNs(pptr, BAD_CAST YAZ_XMLNS_DIAG_v1_1,
1379 xmlNodePtr rptr = xmlNewChild(ptr, ns_diag, BAD_CAST "diagnostics", 0);
1380 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1381 &res->num_diagnostics, client_data,
1384 if (res->extraResponseData_len)
1385 add_XML_n(ptr, "extraResponseData",
1386 res->extraResponseData_buf,
1387 res->extraResponseData_len, ns_srw);
1402 * c-file-style: "Stroustrup"
1403 * indent-tabs-mode: nil
1405 * vim: shiftwidth=4 tabstop=8 expandtab