1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2010 Index Data
3 * See the file LICENSE for details.
7 * \brief Implements SRW/SRU package encoding and decoding
15 #include <libxml/parser.h>
16 #include <libxml/tree.h>
19 static void add_XML_n(xmlNodePtr ptr, const char *elem, char *val, int len,
24 xmlDocPtr doc = xmlParseMemory(val,len);
27 xmlNodePtr c = xmlNewChild(ptr, ns_ptr, BAD_CAST elem, 0);
28 xmlNodePtr t = xmlDocGetRootElement(doc);
29 xmlAddChild(c, xmlCopyNode(t,1));
35 xmlNodePtr add_xsd_string_n(xmlNodePtr ptr, const char *elem, const char *val,
40 xmlNodePtr c = xmlNewChild(ptr, 0, BAD_CAST elem, 0);
41 xmlNodePtr t = xmlNewTextLen(BAD_CAST val, len);
48 xmlNodePtr add_xsd_string_ns(xmlNodePtr ptr, const char *elem, const char *val,
53 xmlNodePtr c = xmlNewChild(ptr, ns_ptr, BAD_CAST elem, 0);
54 xmlNodePtr t = xmlNewText(BAD_CAST val);
61 xmlNodePtr add_xsd_string(xmlNodePtr ptr, const char *elem, const char *val)
63 return add_xsd_string_ns(ptr, elem, val, 0);
66 static void add_xsd_integer(xmlNodePtr ptr, const char *elem,
72 sprintf(str, ODR_INT_PRINTF, *val);
73 xmlNewTextChild(ptr, 0, BAD_CAST elem, BAD_CAST str);
77 static int match_element(xmlNodePtr ptr, const char *elem)
79 if (ptr->type == XML_ELEMENT_NODE && !xmlStrcmp(ptr->name, BAD_CAST elem))
88 static int match_xsd_string_n(xmlNodePtr ptr, const char *elem, ODR o,
92 struct _xmlAttr *attr;
94 if (!match_element(ptr, elem))
97 for (attr = ptr->properties; attr; attr = attr->next)
98 if (!strcmp(attr->name, "type") &&
99 attr->children && attr->children->type == XML_TEXT_NODE)
101 const char *t = strchr(attr->children->content, ':');
105 t = attr->children->content;
106 if (!strcmp(t, "string"))
113 if (!ptr || ptr->type != XML_TEXT_NODE)
118 *val = odr_strdup(o, (const char *) ptr->content);
120 *len = xmlStrlen(ptr->content);
125 static int match_xsd_string(xmlNodePtr ptr, const char *elem, ODR o,
128 return match_xsd_string_n(ptr, elem, o, val, 0);
131 static int match_xsd_XML_n(xmlNodePtr ptr, const char *elem, ODR o,
132 char **val, int *len)
136 if (!match_element(ptr, elem))
139 buf = xmlBufferCreate();
141 /* Copy each element nodes at top.
142 In most cases there is only one root node.. At least one server
143 http://www.theeuropeanlibrary.org/sru/sru.pl
144 has multiple root nodes in recordData.
146 for (ptr = ptr->children; ptr; ptr = ptr->next)
148 if (ptr->type == XML_ELEMENT_NODE)
150 /* copy node to get NS right (bug #740). */
151 xmlNode *tmp = xmlCopyNode(ptr, 1);
153 xmlNodeDump(buf, tmp->doc, tmp, 0, 0);
159 *val = (char *) odr_malloc(o, buf->use+1);
160 memcpy (*val, buf->content, buf->use);
161 (*val)[buf->use] = '\0';
171 static int match_xsd_integer(xmlNodePtr ptr, const char *elem, ODR o,
175 struct _xmlAttr *attr;
177 if (!match_element(ptr, elem))
180 for (attr = ptr->properties; attr; attr = attr->next)
181 if (!strcmp(attr->name, "type") &&
182 attr->children && attr->children->type == XML_TEXT_NODE)
184 const char *t = strchr(attr->children->content, ':');
188 t = attr->children->content;
189 if (!strcmp(t, "integer"))
196 if (!ptr || ptr->type != XML_TEXT_NODE)
198 *val = odr_intdup(o, odr_atoi((const char *) ptr->content));
202 char *yaz_negotiate_sru_version(char *input_ver)
207 if (!strcmp(input_ver, "1.1"))
209 return "1.2"; /* our latest supported version */
212 static int yaz_srw_record(ODR o, xmlNodePtr pptr, Z_SRW_record *rec,
213 Z_SRW_extra_record **extra,
214 void *client_data, const char *ns)
216 if (o->direction == ODR_DECODE)
218 Z_SRW_extra_record ex;
221 int pack = Z_SRW_recordPacking_string;
223 xmlNodePtr data_ptr = 0;
224 rec->recordSchema = 0;
225 rec->recordData_buf = 0;
226 rec->recordData_len = 0;
227 rec->recordPosition = 0;
230 ex.extraRecordData_buf = 0;
231 ex.extraRecordData_len = 0;
232 ex.recordIdentifier = 0;
234 for (ptr = pptr->children; ptr; ptr = ptr->next)
237 if (match_xsd_string(ptr, "recordSchema", o,
240 else if (match_xsd_string(ptr, "recordPacking", o, &spack))
243 pack = yaz_srw_str_to_pack(spack);
245 else if (match_xsd_integer(ptr, "recordPosition", o,
246 &rec->recordPosition))
248 else if (match_element(ptr, "recordData"))
250 /* save position of Data until after the loop
251 then we will know the packing (hopefully), and
252 unpacking is done once
256 else if (match_xsd_XML_n(ptr, "extraRecordData", o,
257 &ex.extraRecordData_buf,
258 &ex.extraRecordData_len) )
260 else if (match_xsd_string(ptr, "recordIdentifier", o,
261 &ex.recordIdentifier))
269 case Z_SRW_recordPacking_XML:
270 match_xsd_XML_n(data_ptr, "recordData", o,
271 &rec->recordData_buf, &rec->recordData_len);
273 case Z_SRW_recordPacking_URL:
274 /* just store it as a string.
275 leave it to the backend to collect the document */
276 match_xsd_string_n(data_ptr, "recordData", o,
277 &rec->recordData_buf, &rec->recordData_len);
279 case Z_SRW_recordPacking_string:
280 match_xsd_string_n(data_ptr, "recordData", o,
281 &rec->recordData_buf, &rec->recordData_len);
285 rec->recordPacking = pack;
286 if (ex.extraRecordData_buf || ex.recordIdentifier)
288 *extra = (Z_SRW_extra_record *)
289 odr_malloc(o, sizeof(Z_SRW_extra_record));
290 memcpy(*extra, &ex, sizeof(Z_SRW_extra_record));
293 else if (o->direction == ODR_ENCODE)
295 xmlNodePtr ptr = pptr;
296 int pack = rec->recordPacking;
297 const char *spack = yaz_srw_pack_to_str(pack);
299 add_xsd_string(ptr, "recordSchema", rec->recordSchema);
301 add_xsd_string(ptr, "recordPacking", spack);
304 case Z_SRW_recordPacking_string:
305 add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
306 rec->recordData_len);
308 case Z_SRW_recordPacking_XML:
309 add_XML_n(ptr, "recordData", rec->recordData_buf,
310 rec->recordData_len, 0);
312 case Z_SRW_recordPacking_URL:
313 add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
314 rec->recordData_len);
317 if (rec->recordPosition)
318 add_xsd_integer(ptr, "recordPosition", rec->recordPosition );
321 if ((*extra)->recordIdentifier)
322 add_xsd_string(ptr, "recordIdentifier",
323 (*extra)->recordIdentifier);
324 if ((*extra)->extraRecordData_buf)
325 add_XML_n(ptr, "extraRecordData",
326 (*extra)->extraRecordData_buf,
327 (*extra)->extraRecordData_len, 0);
333 static int yaz_srw_records(ODR o, xmlNodePtr pptr, Z_SRW_record **recs,
334 Z_SRW_extra_record ***extra,
335 int *num, void *client_data, const char *ns)
337 if (o->direction == ODR_DECODE)
342 for (ptr = pptr->children; ptr; ptr = ptr->next)
344 if (ptr->type == XML_ELEMENT_NODE &&
345 !xmlStrcmp(ptr->name, BAD_CAST "record"))
350 *recs = (Z_SRW_record *) odr_malloc(o, *num * sizeof(**recs));
351 *extra = (Z_SRW_extra_record **) odr_malloc(o, *num * sizeof(**extra));
352 for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next)
354 if (ptr->type == XML_ELEMENT_NODE &&
355 !xmlStrcmp(ptr->name, BAD_CAST "record"))
357 yaz_srw_record(o, ptr, *recs + i, *extra + i, client_data, ns);
362 else if (o->direction == ODR_ENCODE)
365 for (i = 0; i < *num; i++)
367 xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "record",
369 yaz_srw_record(o, rptr, (*recs)+i, (*extra ? *extra + i : 0),
376 static int yaz_srw_version(ODR o, xmlNodePtr pptr, Z_SRW_recordVersion *rec,
377 void *client_data, const char *ns)
379 if (o->direction == ODR_DECODE)
382 rec->versionType = 0;
383 rec->versionValue = 0;
384 for (ptr = pptr->children; ptr; ptr = ptr->next)
387 if (match_xsd_string(ptr, "versionType", o,
390 else if (match_xsd_string(ptr, "versionValue", o,
395 else if (o->direction == ODR_ENCODE)
397 xmlNodePtr ptr = pptr;
398 add_xsd_string(ptr, "versionType", rec->versionType);
399 add_xsd_string(ptr, "versionValue", rec->versionValue);
404 static int yaz_srw_versions(ODR o, xmlNodePtr pptr,
405 Z_SRW_recordVersion **vers,
406 int *num, void *client_data, const char *ns)
408 if (o->direction == ODR_DECODE)
413 for (ptr = pptr->children; ptr; ptr = ptr->next)
415 if (ptr->type == XML_ELEMENT_NODE &&
416 !xmlStrcmp(ptr->name, BAD_CAST "recordVersion"))
421 *vers = (Z_SRW_recordVersion *) odr_malloc(o, *num * sizeof(**vers));
422 for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next)
424 if (ptr->type == XML_ELEMENT_NODE &&
425 !xmlStrcmp(ptr->name, BAD_CAST "recordVersion"))
427 yaz_srw_version(o, ptr, *vers + i, client_data, ns);
432 else if (o->direction == ODR_ENCODE)
435 for (i = 0; i < *num; i++)
437 xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "version",
439 yaz_srw_version(o, rptr, (*vers)+i, client_data, ns);
446 static int yaz_srw_decode_diagnostics(ODR o, xmlNodePtr pptr,
447 Z_SRW_diagnostic **recs, int *num,
448 void *client_data, const char *ns)
454 for (ptr = pptr; ptr; ptr = ptr->next)
456 if (ptr->type == XML_ELEMENT_NODE &&
457 !xmlStrcmp(ptr->name, BAD_CAST "diagnostic"))
462 *recs = (Z_SRW_diagnostic *) odr_malloc(o, *num * sizeof(**recs));
463 for (i = 0; i < *num; i++)
466 (*recs)[i].details = 0;
467 (*recs)[i].message = 0;
469 for (i = 0, ptr = pptr; ptr; ptr = ptr->next)
471 if (ptr->type == XML_ELEMENT_NODE &&
472 !xmlStrcmp(ptr->name, BAD_CAST "diagnostic"))
476 (*recs)[i].details = 0;
477 (*recs)[i].message = 0;
478 for (rptr = ptr->children; rptr; rptr = rptr->next)
480 if (match_xsd_string(rptr, "uri", o,
483 else if (match_xsd_string(rptr, "details", o,
484 &(*recs)[i].details))
486 else if (match_xsd_string(rptr, "message", o,
487 &(*recs)[i].message))
496 int sru_decode_surrogate_diagnostics(const char *buf, size_t len,
497 Z_SRW_diagnostic **diag,
501 xmlDocPtr doc = xmlParseMemory(buf, len);
504 xmlNodePtr ptr = xmlDocGetRootElement(doc);
505 while (ptr && ptr->type != XML_ELEMENT_NODE)
508 && !xmlStrcmp(ptr->ns->href,
509 BAD_CAST "http://www.loc.gov/zing/srw/diagnostic/"))
511 ret = yaz_srw_decode_diagnostics(odr, ptr, diag, num, 0, 0);
518 static int yaz_srw_diagnostics(ODR o, xmlNodePtr pptr, Z_SRW_diagnostic **recs,
519 int *num, void *client_data, const char *ns)
521 if (o->direction == ODR_DECODE)
523 return yaz_srw_decode_diagnostics(o, pptr->children, recs, num, client_data, ns);
525 else if (o->direction == ODR_ENCODE)
529 xmlNewNs(pptr, BAD_CAST YAZ_XMLNS_DIAG_v1_1, BAD_CAST "diag" );
530 for (i = 0; i < *num; i++)
532 const char *std_diag = "info:srw/diagnostic/1/";
533 const char *ucp_diag = "info:srw/diagnostic/12/";
534 xmlNodePtr rptr = xmlNewChild(pptr, ns_diag,
535 BAD_CAST "diagnostic", 0);
536 add_xsd_string(rptr, "uri", (*recs)[i].uri);
537 if ((*recs)[i].message)
538 add_xsd_string(rptr, "message", (*recs)[i].message);
539 else if ((*recs)[i].uri )
541 if (!strncmp((*recs)[i].uri, std_diag, strlen(std_diag)))
543 int no = atoi((*recs)[i].uri + strlen(std_diag));
544 const char *message = yaz_diag_srw_str(no);
546 add_xsd_string(rptr, "message", message);
548 else if (!strncmp((*recs)[i].uri, ucp_diag, strlen(ucp_diag)))
550 int no = atoi((*recs)[i].uri + strlen(ucp_diag));
551 const char *message = yaz_diag_sru_update_str(no);
553 add_xsd_string(rptr, "message", message);
556 add_xsd_string(rptr, "details", (*recs)[i].details);
562 static int yaz_srw_term(ODR o, xmlNodePtr pptr, Z_SRW_scanTerm *term,
563 void *client_data, const char *ns)
565 if (o->direction == ODR_DECODE)
569 term->numberOfRecords = 0;
570 term->displayTerm = 0;
571 term->whereInList = 0;
572 for (ptr = pptr->children; ptr; ptr = ptr->next)
574 if (match_xsd_string(ptr, "value", o, &term->value))
576 else if (match_xsd_integer(ptr, "numberOfRecords", o,
577 &term->numberOfRecords))
579 else if (match_xsd_string(ptr, "displayTerm", o,
582 else if (match_xsd_string(ptr, "whereInList", o,
587 else if (o->direction == ODR_ENCODE)
589 xmlNodePtr ptr = pptr;
590 add_xsd_string(ptr, "value", term->value);
591 add_xsd_integer(ptr, "numberOfRecords", term->numberOfRecords);
592 add_xsd_string(ptr, "displayTerm", term->displayTerm);
593 add_xsd_string(ptr, "whereInList", term->whereInList);
598 static int yaz_srw_terms(ODR o, xmlNodePtr pptr, Z_SRW_scanTerm **terms,
599 int *num, void *client_data, const char *ns)
601 if (o->direction == ODR_DECODE)
606 for (ptr = pptr->children; ptr; ptr = ptr->next)
608 if (ptr->type == XML_ELEMENT_NODE &&
609 !xmlStrcmp(ptr->name, BAD_CAST "term"))
614 *terms = (Z_SRW_scanTerm *) odr_malloc(o, *num * sizeof(**terms));
615 for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next, i++)
617 if (ptr->type == XML_ELEMENT_NODE &&
618 !xmlStrcmp(ptr->name, BAD_CAST "term"))
619 yaz_srw_term(o, ptr, (*terms)+i, client_data, ns);
622 else if (o->direction == ODR_ENCODE)
625 for (i = 0; i < *num; i++)
627 xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "term", 0);
628 yaz_srw_term(o, rptr, (*terms)+i, client_data, ns);
634 int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
635 void *client_data, const char *ns)
637 xmlNodePtr pptr = (xmlNodePtr) vptr;
638 if (o->direction == ODR_DECODE)
640 Z_SRW_PDU **p = handler_data;
641 xmlNodePtr method = pptr->children;
644 while (method && method->type == XML_TEXT_NODE)
645 method = method->next;
649 if (method->type != XML_ELEMENT_NODE)
652 *p = yaz_srw_get_core_v_1_1(o);
654 if (!xmlStrcmp(method->name, BAD_CAST "searchRetrieveRequest"))
656 xmlNodePtr ptr = method->children;
657 Z_SRW_searchRetrieveRequest *req;
659 (*p)->which = Z_SRW_searchRetrieve_request;
660 req = (*p)->u.request = (Z_SRW_searchRetrieveRequest *)
661 odr_malloc(o, sizeof(*req));
662 req->query_type = Z_SRW_query_type_cql;
664 req->sort_type = Z_SRW_sort_type_none;
666 req->startRecord = 0;
667 req->maximumRecords = 0;
668 req->recordSchema = 0;
669 req->recordPacking = 0;
670 req->recordXPath = 0;
671 req->resultSetTTL = 0;
675 for (; ptr; ptr = ptr->next)
677 if (match_xsd_string(ptr, "version", o,
680 else if (match_xsd_string(ptr, "query", o,
682 req->query_type = Z_SRW_query_type_cql;
683 else if (match_xsd_string(ptr, "pQuery", o,
685 req->query_type = Z_SRW_query_type_pqf;
686 else if (match_xsd_string(ptr, "xQuery", o,
688 req->query_type = Z_SRW_query_type_xcql;
689 else if (match_xsd_integer(ptr, "startRecord", o,
692 else if (match_xsd_integer(ptr, "maximumRecords", o,
693 &req->maximumRecords))
695 else if (match_xsd_string(ptr, "recordPacking", o,
696 &req->recordPacking))
698 else if (match_xsd_string(ptr, "recordSchema", o,
701 else if (match_xsd_string(ptr, "recordXPath", o,
704 else if (match_xsd_integer(ptr, "resultSetTTL", o,
707 else if (match_xsd_string(ptr, "sortKeys", o,
708 &req->sort.sortKeys))
709 req->sort_type = Z_SRW_sort_type_sort;
710 else if (match_xsd_string(ptr, "stylesheet", o,
713 else if (match_xsd_string(ptr, "database", o,
717 if (!req->query.cql && !req->query.pqf && !req->query.xcql)
719 /* should put proper diagnostic here */
723 else if (!xmlStrcmp(method->name, BAD_CAST "searchRetrieveResponse"))
725 xmlNodePtr ptr = method->children;
726 Z_SRW_searchRetrieveResponse *res;
728 (*p)->which = Z_SRW_searchRetrieve_response;
729 res = (*p)->u.response = (Z_SRW_searchRetrieveResponse *)
730 odr_malloc(o, sizeof(*res));
732 res->numberOfRecords = 0;
733 res->resultSetId = 0;
734 res->resultSetIdleTime = 0;
736 res->num_records = 0;
737 res->diagnostics = 0;
738 res->num_diagnostics = 0;
739 res->nextRecordPosition = 0;
742 for (; ptr; ptr = ptr->next)
744 if (match_xsd_string(ptr, "version", o,
747 else if (match_xsd_XML_n(ptr, "extraResponseData", o,
748 &(*p)->extraResponseData_buf,
749 &(*p)->extraResponseData_len))
751 else if (match_xsd_integer(ptr, "numberOfRecords", o,
752 &res->numberOfRecords))
754 else if (match_xsd_string(ptr, "resultSetId", o,
757 else if (match_xsd_integer(ptr, "resultSetIdleTime", o,
758 &res->resultSetIdleTime))
760 else if (match_element(ptr, "records"))
761 yaz_srw_records(o, ptr, &res->records,
763 &res->num_records, client_data, ns);
764 else if (match_xsd_integer(ptr, "nextRecordPosition", o,
765 &res->nextRecordPosition))
767 else if (match_element(ptr, "diagnostics"))
768 yaz_srw_diagnostics(o, ptr, &res->diagnostics,
769 &res->num_diagnostics,
773 else if (!xmlStrcmp(method->name, BAD_CAST "explainRequest"))
775 Z_SRW_explainRequest *req;
776 xmlNodePtr ptr = method->children;
778 (*p)->which = Z_SRW_explain_request;
779 req = (*p)->u.explain_request = (Z_SRW_explainRequest *)
780 odr_malloc(o, sizeof(*req));
781 req->recordPacking = 0;
784 for (; ptr; ptr = ptr->next)
786 if (match_xsd_string(ptr, "version", o,
789 else if (match_xsd_XML_n(ptr, "extraResponseData", o,
790 &(*p)->extraResponseData_buf,
791 &(*p)->extraResponseData_len))
793 else if (match_xsd_string(ptr, "stylesheet", o,
796 else if (match_xsd_string(ptr, "recordPacking", o,
797 &req->recordPacking))
799 else if (match_xsd_string(ptr, "database", o,
804 else if (!xmlStrcmp(method->name, BAD_CAST "explainResponse"))
806 Z_SRW_explainResponse *res;
807 xmlNodePtr ptr = method->children;
809 (*p)->which = Z_SRW_explain_response;
810 res = (*p)->u.explain_response = (Z_SRW_explainResponse*)
811 odr_malloc(o, sizeof(*res));
812 res->diagnostics = 0;
813 res->num_diagnostics = 0;
814 res->record.recordSchema = 0;
815 res->record.recordData_buf = 0;
816 res->record.recordData_len = 0;
817 res->record.recordPosition = 0;
819 for (; ptr; ptr = ptr->next)
821 if (match_xsd_string(ptr, "version", o,
824 else if (match_xsd_XML_n(ptr, "extraResponseData", o,
825 &(*p)->extraResponseData_buf,
826 &(*p)->extraResponseData_len))
828 else if (match_element(ptr, "record"))
829 yaz_srw_record(o, ptr, &res->record, &res->extra_record,
831 else if (match_element(ptr, "diagnostics"))
832 yaz_srw_diagnostics(o, ptr, &res->diagnostics,
833 &res->num_diagnostics,
838 else if (!xmlStrcmp(method->name, BAD_CAST "scanRequest"))
840 Z_SRW_scanRequest *req;
841 xmlNodePtr ptr = method->children;
843 (*p)->which = Z_SRW_scan_request;
844 req = (*p)->u.scan_request = (Z_SRW_scanRequest *)
845 odr_malloc(o, sizeof(*req));
846 req->query_type = Z_SRW_query_type_cql;
847 req->scanClause.cql = 0;
848 req->responsePosition = 0;
849 req->maximumTerms = 0;
853 for (; ptr; ptr = ptr->next)
855 if (match_xsd_string(ptr, "version", o,
858 else if (match_xsd_XML_n(ptr, "extraResponseData", o,
859 &(*p)->extraResponseData_buf,
860 &(*p)->extraResponseData_len))
862 else if (match_xsd_string(ptr, "scanClause", o,
863 &req->scanClause.cql))
865 else if (match_xsd_string(ptr, "pScanClause", o,
866 &req->scanClause.pqf))
868 req->query_type = Z_SRW_query_type_pqf;
870 else if (match_xsd_integer(ptr, "responsePosition", o,
871 &req->responsePosition))
873 else if (match_xsd_integer(ptr, "maximumTerms", o,
876 else if (match_xsd_string(ptr, "stylesheet", o,
879 else if (match_xsd_string(ptr, "database", o,
884 else if (!xmlStrcmp(method->name, BAD_CAST "scanResponse"))
886 Z_SRW_scanResponse *res;
887 xmlNodePtr ptr = method->children;
889 (*p)->which = Z_SRW_scan_response;
890 res = (*p)->u.scan_response = (Z_SRW_scanResponse *)
891 odr_malloc(o, sizeof(*res));
894 res->diagnostics = 0;
895 res->num_diagnostics = 0;
897 for (; ptr; ptr = ptr->next)
899 if (match_xsd_string(ptr, "version", o,
902 else if (match_xsd_XML_n(ptr, "extraResponseData", o,
903 &(*p)->extraResponseData_buf,
904 &(*p)->extraResponseData_len))
906 else if (match_element(ptr, "terms"))
907 yaz_srw_terms(o, ptr, &res->terms,
908 &res->num_terms, client_data,
910 else if (match_element(ptr, "diagnostics"))
911 yaz_srw_diagnostics(o, ptr, &res->diagnostics,
912 &res->num_diagnostics,
921 neg_version = yaz_negotiate_sru_version((*p)->srw_version);
923 (*p)->srw_version = neg_version;
925 else if (o->direction == ODR_ENCODE)
927 Z_SRW_PDU **p = handler_data;
931 if ((*p)->which == Z_SRW_searchRetrieve_request)
933 Z_SRW_searchRetrieveRequest *req = (*p)->u.request;
934 ptr = xmlNewChild(pptr, 0, BAD_CAST "searchRetrieveRequest", 0);
935 ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
936 xmlSetNs(ptr, ns_srw);
938 if ((*p)->srw_version)
939 add_xsd_string(ptr, "version", (*p)->srw_version);
940 switch(req->query_type)
942 case Z_SRW_query_type_cql:
943 add_xsd_string(ptr, "query", req->query.cql);
945 case Z_SRW_query_type_xcql:
946 add_xsd_string(ptr, "xQuery", req->query.xcql);
948 case Z_SRW_query_type_pqf:
949 add_xsd_string(ptr, "pQuery", req->query.pqf);
952 add_xsd_integer(ptr, "startRecord", req->startRecord);
953 add_xsd_integer(ptr, "maximumRecords", req->maximumRecords);
954 add_xsd_string(ptr, "recordPacking", req->recordPacking);
955 add_xsd_string(ptr, "recordSchema", req->recordSchema);
956 add_xsd_string(ptr, "recordXPath", req->recordXPath);
957 add_xsd_integer(ptr, "resultSetTTL", req->resultSetTTL);
958 switch(req->sort_type)
960 case Z_SRW_sort_type_none:
962 case Z_SRW_sort_type_sort:
963 add_xsd_string(ptr, "sortKeys", req->sort.sortKeys);
965 case Z_SRW_sort_type_xSort:
966 add_xsd_string(ptr, "xSortKeys", req->sort.xSortKeys);
969 add_xsd_string(ptr, "stylesheet", req->stylesheet);
970 add_xsd_string(ptr, "database", req->database);
972 else if ((*p)->which == Z_SRW_searchRetrieve_response)
974 Z_SRW_searchRetrieveResponse *res = (*p)->u.response;
975 ptr = xmlNewChild(pptr, 0, BAD_CAST "searchRetrieveResponse", 0);
976 ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
977 xmlSetNs(ptr, ns_srw);
979 if ((*p)->srw_version)
980 add_xsd_string(ptr, "version", (*p)->srw_version);
981 add_xsd_integer(ptr, "numberOfRecords", res->numberOfRecords);
982 add_xsd_string(ptr, "resultSetId", res->resultSetId);
983 add_xsd_integer(ptr, "resultSetIdleTime", res->resultSetIdleTime);
984 if (res->num_records)
986 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "records", 0);
987 yaz_srw_records(o, rptr, &res->records, &res->extra_records,
991 add_xsd_integer(ptr, "nextRecordPosition",
992 res->nextRecordPosition);
993 if (res->num_diagnostics)
995 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
997 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
998 &res->num_diagnostics, client_data, ns);
1001 else if ((*p)->which == Z_SRW_explain_request)
1003 Z_SRW_explainRequest *req = (*p)->u.explain_request;
1004 ptr = xmlNewChild(pptr, 0, BAD_CAST "explainRequest", 0);
1005 ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1006 xmlSetNs(ptr, ns_srw);
1008 add_xsd_string(ptr, "version", (*p)->srw_version);
1009 add_xsd_string(ptr, "recordPacking", req->recordPacking);
1010 add_xsd_string(ptr, "stylesheet", req->stylesheet);
1011 add_xsd_string(ptr, "database", req->database);
1013 else if ((*p)->which == Z_SRW_explain_response)
1015 Z_SRW_explainResponse *res = (*p)->u.explain_response;
1016 ptr = xmlNewChild(pptr, 0, BAD_CAST "explainResponse", 0);
1017 ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1018 xmlSetNs(ptr, ns_srw);
1020 add_xsd_string(ptr, "version", (*p)->srw_version);
1023 xmlNodePtr ptr1 = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
1024 yaz_srw_record(o, ptr1, &res->record, &res->extra_record,
1027 if (res->num_diagnostics)
1029 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
1031 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1032 &res->num_diagnostics, client_data, ns);
1035 else if ((*p)->which == Z_SRW_scan_request)
1037 Z_SRW_scanRequest *req = (*p)->u.scan_request;
1038 ptr = xmlNewChild(pptr, 0, BAD_CAST "scanRequest", 0);
1039 ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1040 xmlSetNs(ptr, ns_srw);
1042 add_xsd_string(ptr, "version", (*p)->srw_version);
1043 switch(req->query_type)
1045 case Z_SRW_query_type_cql:
1046 add_xsd_string(ptr, "scanClause", req->scanClause.cql);
1048 case Z_SRW_query_type_pqf:
1049 add_xsd_string(ptr, "pScanClause", req->scanClause.pqf);
1052 add_xsd_integer(ptr, "responsePosition", req->responsePosition);
1053 add_xsd_integer(ptr, "maximumTerms", req->maximumTerms);
1054 add_xsd_string(ptr, "stylesheet", req->stylesheet);
1055 add_xsd_string(ptr, "database", req->database);
1057 else if ((*p)->which == Z_SRW_scan_response)
1059 Z_SRW_scanResponse *res = (*p)->u.scan_response;
1060 ptr = xmlNewChild(pptr, 0, BAD_CAST "scanResponse", 0);
1061 ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1062 xmlSetNs(ptr, ns_srw);
1064 add_xsd_string(ptr, "version", (*p)->srw_version);
1068 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "terms", 0);
1069 yaz_srw_terms(o, rptr, &res->terms, &res->num_terms,
1072 if (res->num_diagnostics)
1074 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
1076 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1077 &res->num_diagnostics, client_data, ns);
1082 if (ptr && (*p)->extraResponseData_len)
1083 add_XML_n(ptr, "extraResponseData",
1084 (*p)->extraResponseData_buf,
1085 (*p)->extraResponseData_len, ns_srw);
1092 int yaz_ucp_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
1093 void *client_data, const char *ns_ucp_str)
1095 xmlNodePtr pptr = (xmlNodePtr) vptr;
1096 const char *ns_srw_str = YAZ_XMLNS_SRU_v1_1;
1097 if (o->direction == ODR_DECODE)
1099 Z_SRW_PDU **p = handler_data;
1100 xmlNodePtr method = pptr->children;
1102 while (method && method->type == XML_TEXT_NODE)
1103 method = method->next;
1107 if (method->type != XML_ELEMENT_NODE)
1110 *p = yaz_srw_get_core_v_1_1(o);
1112 if (!xmlStrcmp(method->name, BAD_CAST "updateRequest"))
1114 xmlNodePtr ptr = method->children;
1115 Z_SRW_updateRequest *req;
1118 (*p)->which = Z_SRW_update_request;
1119 req = (*p)->u.update_request = (Z_SRW_updateRequest *)
1120 odr_malloc(o, sizeof(*req));
1124 req->recordVersions = 0;
1125 req->num_recordVersions = 0;
1127 req->extra_record = 0;
1128 req->extraRequestData_buf = 0;
1129 req->extraRequestData_len = 0;
1130 req->stylesheet = 0;
1132 for (; ptr; ptr = ptr->next)
1134 if (match_xsd_string(ptr, "version", o,
1135 &(*p)->srw_version))
1137 else if (match_xsd_string(ptr, "action", o,
1140 if ( !strcmp(oper, "info:srw/action/1/delete"))
1141 req->operation = "delete";
1142 else if (!strcmp(oper,"info:srw/action/1/replace" ))
1143 req->operation = "replace";
1144 else if ( !strcmp( oper, "info:srw/action/1/create"))
1145 req->operation = "insert";
1148 else if (match_xsd_string(ptr, "recordIdentifier", o,
1151 else if (match_element(ptr, "recordVersions" ) )
1152 yaz_srw_versions( o, ptr, &req->recordVersions,
1153 &req->num_recordVersions, client_data,
1155 else if (match_element(ptr, "record"))
1157 req->record = yaz_srw_get_record(o);
1158 yaz_srw_record(o, ptr, req->record, &req->extra_record,
1159 client_data, ns_ucp_str);
1161 else if (match_xsd_string(ptr, "stylesheet", o,
1164 else if (match_xsd_string(ptr, "database", o,
1169 else if (!xmlStrcmp(method->name, BAD_CAST "updateResponse"))
1171 xmlNodePtr ptr = method->children;
1172 Z_SRW_updateResponse *res;
1174 (*p)->which = Z_SRW_update_response;
1175 res = (*p)->u.update_response = (Z_SRW_updateResponse *)
1176 odr_malloc(o, sizeof(*res));
1178 res->operationStatus = 0;
1180 res->recordVersions = 0;
1181 res->num_recordVersions = 0;
1182 res->diagnostics = 0;
1183 res->num_diagnostics = 0;
1185 res->extra_record = 0;
1186 res->extraResponseData_buf = 0;
1187 res->extraResponseData_len = 0;
1189 for (; ptr; ptr = ptr->next)
1191 if (match_xsd_string(ptr, "version", o,
1192 &(*p)->srw_version))
1194 else if (match_xsd_string(ptr, "operationStatus", o,
1195 &res->operationStatus ))
1197 else if (match_xsd_string(ptr, "recordIdentifier", o,
1200 else if (match_element(ptr, "recordVersions" ))
1201 yaz_srw_versions(o, ptr, &res->recordVersions,
1202 &res->num_recordVersions,
1203 client_data, ns_ucp_str);
1204 else if (match_element(ptr, "record"))
1206 res->record = yaz_srw_get_record(o);
1207 yaz_srw_record(o, ptr, res->record, &res->extra_record,
1208 client_data, ns_ucp_str);
1210 else if (match_element(ptr, "diagnostics"))
1211 yaz_srw_diagnostics(o, ptr, &res->diagnostics,
1212 &res->num_diagnostics,
1213 client_data, ns_ucp_str);
1216 else if (!xmlStrcmp(method->name, BAD_CAST "explainUpdateRequest"))
1219 else if (!xmlStrcmp(method->name, BAD_CAST "explainUpdateResponse"))
1228 else if (o->direction == ODR_ENCODE)
1230 Z_SRW_PDU **p = handler_data;
1231 xmlNsPtr ns_ucp, ns_srw;
1234 if ((*p)->which == Z_SRW_update_request)
1236 Z_SRW_updateRequest *req = (*p)->u.update_request;
1237 xmlNodePtr ptr = xmlNewChild(pptr, 0, BAD_CAST "updateRequest", 0);
1238 ns_ucp = xmlNewNs(ptr, BAD_CAST ns_ucp_str, BAD_CAST "zu");
1239 xmlSetNs(ptr, ns_ucp);
1240 ns_srw = xmlNewNs(ptr, BAD_CAST ns_srw_str, BAD_CAST "zs");
1242 add_xsd_string_ns(ptr, "version", (*p)->srw_version, ns_srw);
1243 add_xsd_string(ptr, "action", req->operation);
1244 add_xsd_string(ptr, "recordIdentifier", req->recordId );
1245 if (req->recordVersions)
1246 yaz_srw_versions( o, ptr, &req->recordVersions,
1247 &req->num_recordVersions,
1248 client_data, ns_ucp_str);
1249 if (req->record && req->record->recordData_len)
1251 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
1252 xmlSetNs(rptr, ns_srw);
1253 yaz_srw_record(o, rptr, req->record, &req->extra_record,
1254 client_data, ns_ucp_str);
1256 if (req->extraRequestData_len)
1258 add_XML_n(ptr, "extraRequestData",
1259 req->extraRequestData_buf,
1260 req->extraRequestData_len, ns_srw);
1262 add_xsd_string(ptr, "stylesheet", req->stylesheet);
1263 add_xsd_string(ptr, "database", req->database);
1265 else if ((*p)->which == Z_SRW_update_response)
1267 Z_SRW_updateResponse *res = (*p)->u.update_response;
1268 xmlNodePtr ptr = xmlNewChild(pptr, 0, (xmlChar *)
1269 "updateResponse", 0);
1270 ns_ucp = xmlNewNs(ptr, BAD_CAST ns_ucp_str, BAD_CAST "zu");
1271 xmlSetNs(ptr, ns_ucp);
1272 ns_srw = xmlNewNs(ptr, BAD_CAST ns_srw_str, BAD_CAST "zs");
1274 add_xsd_string_ns(ptr, "version", (*p)->srw_version, ns_srw);
1275 add_xsd_string(ptr, "operationStatus", res->operationStatus );
1276 add_xsd_string(ptr, "recordIdentifier", res->recordId );
1277 if (res->recordVersions)
1278 yaz_srw_versions(o, ptr, &res->recordVersions,
1279 &res->num_recordVersions,
1280 client_data, ns_ucp_str);
1281 if (res->record && res->record->recordData_len)
1283 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
1284 xmlSetNs(rptr, ns_srw);
1285 yaz_srw_record(o, rptr, res->record, &res->extra_record,
1286 client_data, ns_ucp_str);
1288 if (res->num_diagnostics)
1291 xmlNewNs(pptr, BAD_CAST YAZ_XMLNS_DIAG_v1_1,
1294 xmlNodePtr rptr = xmlNewChild(ptr, ns_diag, BAD_CAST "diagnostics", 0);
1295 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1296 &res->num_diagnostics, client_data,
1299 if (res->extraResponseData_len)
1300 add_XML_n(ptr, "extraResponseData",
1301 res->extraResponseData_buf,
1302 res->extraResponseData_len, ns_srw);
1317 * c-file-style: "Stroustrup"
1318 * indent-tabs-mode: nil
1320 * vim: shiftwidth=4 tabstop=8 expandtab