Version 5.13.0
[yaz-moved-to-github.git] / src / srw.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file srw.c
7  * \brief Implements SRW/SRU package encoding and decoding
8  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <stdlib.h>
14
15 #include <yaz/srw.h>
16 #include <yaz/wrbuf.h>
17 #if YAZ_HAVE_XML2
18 #include <libxml/parser.h>
19 #include <libxml/tree.h>
20 #include <assert.h>
21 #include <yaz/facet.h>
22 #include <yaz/proto.h>
23 #include "sru-p.h"
24
25 char *yaz_negotiate_sru_version(char *input_ver)
26 {
27     if (!input_ver)
28         return "2.0";
29     if (!strcmp(input_ver, "1.1"))
30         return "1.1";
31     if (!strncmp(input_ver, "1.", 2))
32         return "1.2";
33     if (!strncmp(input_ver, "2.", 2))
34         return "2.0";
35     return 0;
36 }
37
38 static int yaz_srw_record(ODR o, xmlNodePtr pptr, Z_SRW_record *rec,
39                           Z_SRW_extra_record **extra,
40                           void *client_data, int version2)
41 {
42     if (o->direction == ODR_DECODE)
43     {
44         Z_SRW_extra_record ex;
45
46         char *spack = 0;
47         xmlNodePtr ptr;
48 #ifdef Z_SRW_packed
49         rec->packing = 0;
50 #endif
51         rec->recordSchema = 0;
52         rec->recordData_buf = 0;
53         rec->recordData_len = 0;
54         rec->recordPosition = 0;
55         *extra = 0;
56
57         ex.extraRecordData_buf = 0;
58         ex.extraRecordData_len = 0;
59         ex.recordIdentifier = 0;
60
61         for (ptr = pptr->children; ptr; ptr = ptr->next)
62         {
63
64             if (yaz_match_xsd_string(ptr, "recordSchema", o,
65                                      &rec->recordSchema))
66                 ;
67             else if (yaz_match_xsd_string(ptr, "recordPacking", o, &spack))
68                 ;  /* can't rely on it: in SRU 2.0 it's different semantics */
69             else if (yaz_match_xsd_integer(ptr, "recordPosition", o,
70                                            &rec->recordPosition))
71                 ;
72             else if (yaz_match_xsd_element(ptr, "recordData"))
73             {
74                 /* we assume XML packing, if any element nodes exist below
75                    recordData. Unfortunately, in SRU 2.0 recordPacking
76                    means something different */
77                 xmlNode *p = ptr->children;
78                 for (; p; p = p->next)
79                     if (p->type == XML_ELEMENT_NODE)
80                         break;
81                 if (p)
82                 {
83                     yaz_match_xsd_XML_n2(
84                         ptr, "recordData", o,
85                         &rec->recordData_buf, &rec->recordData_len, 1);
86                     rec->recordPacking = Z_SRW_recordPacking_XML;
87                 }
88                 else
89                 {
90                     yaz_match_xsd_string_n(
91                         ptr, "recordData", o,
92                         &rec->recordData_buf, &rec->recordData_len);
93                     rec->recordPacking = Z_SRW_recordPacking_string;
94                 }
95             }
96             else if (yaz_match_xsd_XML_n(ptr, "extraRecordData", o,
97                                          &ex.extraRecordData_buf,
98                                          &ex.extraRecordData_len) )
99                 ;
100             else
101                 yaz_match_xsd_string(ptr, "recordIdentifier", o,
102                                      &ex.recordIdentifier);
103         }
104         if (ex.extraRecordData_buf || ex.recordIdentifier)
105         {
106             *extra = (Z_SRW_extra_record *)
107                 odr_malloc(o, sizeof(Z_SRW_extra_record));
108             memcpy(*extra, &ex, sizeof(Z_SRW_extra_record));
109         }
110     }
111     else if (o->direction == ODR_ENCODE)
112     {
113         xmlNodePtr ptr = pptr;
114         int pack = rec->recordPacking;
115         const char *spack = yaz_srw_pack_to_str(pack);
116
117         /* recordSchema and recordData are required */
118         if (!rec->recordSchema)
119             xmlNewChild(ptr, 0, BAD_CAST "recordSchema", 0);
120         else
121             add_xsd_string(ptr, "recordSchema", rec->recordSchema);
122         if (spack)
123         {
124             if (version2)
125                 add_xsd_string(ptr, "recordXMLEscaping", spack);
126             else
127                 add_xsd_string(ptr, "recordPacking", spack);
128         }
129         if (!rec->recordData_buf)
130             xmlNewChild(ptr, 0, BAD_CAST "recordData", 0);
131         else
132         {
133             switch (pack)
134             {
135             case Z_SRW_recordPacking_string:
136                 add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
137                                  rec->recordData_len);
138                 break;
139             case Z_SRW_recordPacking_XML:
140                 add_XML_n(ptr, "recordData", rec->recordData_buf,
141                           rec->recordData_len, 0);
142                 break;
143             case Z_SRW_recordPacking_URL:
144                 add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
145                                  rec->recordData_len);
146                 break;
147             }
148         }
149         if (rec->recordPosition)
150             add_xsd_integer(ptr, "recordPosition", rec->recordPosition );
151         if (extra && *extra)
152         {
153             if ((*extra)->recordIdentifier)
154                 add_xsd_string(ptr, "recordIdentifier",
155                                (*extra)->recordIdentifier);
156             if ((*extra)->extraRecordData_buf)
157                 add_XML_n(ptr, "extraRecordData",
158                           (*extra)->extraRecordData_buf,
159                           (*extra)->extraRecordData_len, 0);
160         }
161     }
162     return 0;
163 }
164
165 static int yaz_srw_records(ODR o, xmlNodePtr pptr, Z_SRW_record **recs,
166                            Z_SRW_extra_record ***extra,
167                            int *num, void *client_data, int version2)
168 {
169     if (o->direction == ODR_DECODE)
170     {
171         int i;
172         xmlNodePtr ptr;
173         *num = 0;
174         for (ptr = pptr->children; ptr; ptr = ptr->next)
175         {
176             if (ptr->type == XML_ELEMENT_NODE &&
177                 !xmlStrcmp(ptr->name, BAD_CAST "record"))
178                 (*num)++;
179         }
180         if (!*num)
181             return 1;
182         *recs = (Z_SRW_record *) odr_malloc(o, *num * sizeof(**recs));
183         *extra = (Z_SRW_extra_record **) odr_malloc(o, *num * sizeof(**extra));
184         for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next)
185         {
186             if (ptr->type == XML_ELEMENT_NODE &&
187                 !xmlStrcmp(ptr->name, BAD_CAST "record"))
188             {
189                 yaz_srw_record(o, ptr, *recs + i, *extra + i, client_data, 0);
190                 i++;
191             }
192         }
193     }
194     else if (o->direction == ODR_ENCODE)
195     {
196         int i;
197         for (i = 0; i < *num; i++)
198         {
199             xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "record",
200                                           0);
201             yaz_srw_record(o, rptr, (*recs)+i, (*extra ? *extra + i : 0),
202                            client_data, version2);
203         }
204     }
205     return 0;
206 }
207
208 static int yaz_srw_version(ODR o, xmlNodePtr pptr, Z_SRW_recordVersion *rec,
209                            void *client_data, const char *ns)
210 {
211     if (o->direction == ODR_DECODE)
212     {
213         xmlNodePtr ptr;
214         rec->versionType = 0;
215         rec->versionValue = 0;
216         for (ptr = pptr->children; ptr; ptr = ptr->next)
217         {
218
219             if (yaz_match_xsd_string(ptr, "versionType", o,
220                                      &rec->versionType))
221                 ;
222             else
223                 yaz_match_xsd_string(ptr, "versionValue", o,
224                                      &rec->versionValue);
225         }
226     }
227     else if (o->direction == ODR_ENCODE)
228     {
229         xmlNodePtr ptr = pptr;
230         add_xsd_string(ptr, "versionType", rec->versionType);
231         add_xsd_string(ptr, "versionValue", rec->versionValue);
232     }
233     return 0;
234 }
235
236 static int yaz_srw_versions(ODR o, xmlNodePtr pptr,
237                             Z_SRW_recordVersion **vers,
238                             int *num, void *client_data, const char *ns)
239 {
240     if (o->direction == ODR_DECODE)
241     {
242         int i;
243         xmlNodePtr ptr;
244         *num = 0;
245         for (ptr = pptr->children; ptr; ptr = ptr->next)
246         {
247             if (ptr->type == XML_ELEMENT_NODE &&
248                 !xmlStrcmp(ptr->name, BAD_CAST "recordVersion"))
249                 (*num)++;
250         }
251         if (!*num)
252             return 1;
253         *vers = (Z_SRW_recordVersion *) odr_malloc(o, *num * sizeof(**vers));
254         for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next)
255         {
256             if (ptr->type == XML_ELEMENT_NODE &&
257                 !xmlStrcmp(ptr->name, BAD_CAST "recordVersion"))
258             {
259                 yaz_srw_version(o, ptr, *vers + i, client_data, ns);
260                 i++;
261             }
262         }
263     }
264     else if (o->direction == ODR_ENCODE)
265     {
266         int i;
267         for (i = 0; i < *num; i++)
268         {
269             xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "version",
270                                           0);
271             yaz_srw_version(o, rptr, (*vers)+i, client_data, ns);
272         }
273     }
274     return 0;
275 }
276
277 Z_FacetTerm *yaz_sru_proxy_get_facet_term_count(ODR odr, xmlNodePtr node)
278 {
279     Odr_int freq;
280     xmlNodePtr child;
281     WRBUF wrbuf = wrbuf_alloc();
282     Z_FacetTerm *facet_term;
283     const char *freq_string = yaz_element_attribute_value_get(
284         node, "facetvalue", "est_representation");
285     if (freq_string)
286         freq = odr_atoi(freq_string);
287     else
288         freq = -1;
289
290     for (child = node->children; child ; child = child->next)
291     {
292         if (child->type == XML_TEXT_NODE)
293             wrbuf_puts(wrbuf, (const char *) child->content);
294     }
295     facet_term = facet_term_create_cstr(odr, wrbuf_cstr(wrbuf), freq);
296     wrbuf_destroy(wrbuf);
297     return facet_term;
298 }
299
300 static Z_FacetField *yaz_sru_proxy_decode_facet_field(ODR odr, xmlNodePtr ptr)
301 {
302     Z_AttributeList *list;
303     Z_FacetField *facet_field;
304     int num_terms = 0;
305     int index = 0;
306     xmlNodePtr node;
307     /* USE attribute */
308     const char* name = yaz_element_attribute_value_get(ptr, "facet", "code");
309     yaz_log(YLOG_DEBUG, "sru-proxy facet type: %s", name);
310
311     list = zget_AttributeList_use_string(odr, name);
312     for (node = ptr->children; node; node = node->next) {
313         if (yaz_match_xsd_element(node, "facetvalue"))
314             num_terms++;
315     }
316     facet_field = facet_field_create(odr, list, num_terms);
317     index = 0;
318     for (node = ptr->children; node; node = node->next)
319     {
320         if (yaz_match_xsd_element(node, "facetvalue"))
321         {
322             facet_field_term_set(odr, facet_field,
323                                  yaz_sru_proxy_get_facet_term_count(odr, node),
324                                  index);
325             index++;
326         }
327     }
328     return facet_field;
329 }
330
331 static int yaz_sru_proxy_decode_facets(ODR o, xmlNodePtr root,
332                                        Z_FacetList **facetList)
333 {
334     xmlNodePtr ptr;
335
336     for (ptr = root->children; ptr; ptr = ptr->next)
337     {
338         if (yaz_match_xsd_element(ptr, "facets"))
339         {
340             xmlNodePtr node;
341             Z_FacetList *facet_list;
342             int num_facets = 0;
343             for (node = ptr->children; node; node= node->next)
344             {
345                 if (node->type == XML_ELEMENT_NODE)
346                     num_facets++;
347             }
348             facet_list = facet_list_create(o, num_facets);
349             num_facets = 0;
350             for (node = ptr->children; node; node= node->next)
351             {
352                 if (yaz_match_xsd_element(node, "facet"))
353                 {
354                     facet_list_field_set(
355                         o, facet_list,
356                         yaz_sru_proxy_decode_facet_field(o, node), num_facets);
357                     num_facets++;
358                 }
359             }
360             *facetList = facet_list;
361             break;
362         }
363     }
364     return 0;
365 }
366
367
368
369 static int yaz_srw_decode_diagnostics(ODR o, xmlNodePtr pptr,
370                                       Z_SRW_diagnostic **recs, int *num,
371                                       void *client_data, const char *ns)
372 {
373     int i;
374     xmlNodePtr ptr;
375     *num = 0;
376     for (ptr = pptr; ptr; ptr = ptr->next)
377     {
378         if (ptr->type == XML_ELEMENT_NODE &&
379             !xmlStrcmp(ptr->name, BAD_CAST "diagnostic"))
380             (*num)++;
381     }
382     if (!*num)
383         return 1;
384     *recs = (Z_SRW_diagnostic *) odr_malloc(o, *num * sizeof(**recs));
385     for (i = 0; i < *num; i++)
386     {
387         (*recs)[i].uri = 0;
388         (*recs)[i].details = 0;
389         (*recs)[i].message = 0;
390     }
391     for (i = 0, ptr = pptr; ptr; ptr = ptr->next)
392     {
393         if (ptr->type == XML_ELEMENT_NODE &&
394             !xmlStrcmp(ptr->name, BAD_CAST "diagnostic"))
395         {
396             xmlNodePtr rptr;
397             (*recs)[i].uri = 0;
398             (*recs)[i].details = 0;
399             (*recs)[i].message = 0;
400             for (rptr = ptr->children; rptr; rptr = rptr->next)
401             {
402                 if (yaz_match_xsd_string(rptr, "uri", o, &(*recs)[i].uri))
403                     ;
404                 else if (yaz_match_xsd_string(rptr, "details", o,
405                                               &(*recs)[i].details))
406                     ;
407                 else
408                     yaz_match_xsd_string(rptr, "message", o,
409                                          &(*recs)[i].message);
410             }
411             i++;
412         }
413     }
414     return 0;
415 }
416
417 int sru_decode_surrogate_diagnostics(const char *buf, size_t len,
418                                      Z_SRW_diagnostic **diag,
419                                      int *num, ODR odr)
420 {
421     int ret = 0;
422     xmlDocPtr doc = xmlParseMemory(buf, len);
423     if (doc)
424     {
425         xmlNodePtr ptr = xmlDocGetRootElement(doc);
426         while (ptr && ptr->type != XML_ELEMENT_NODE)
427             ptr = ptr->next;
428         if (ptr && ptr->ns
429             && !xmlStrcmp(ptr->ns->href,
430                           BAD_CAST "http://www.loc.gov/zing/srw/diagnostic/"))
431         {
432             ret = yaz_srw_decode_diagnostics(odr, ptr, diag, num, 0, 0);
433         }
434         xmlFreeDoc(doc);
435     }
436     return ret;
437 }
438
439 static int yaz_srw_diagnostics(ODR o, xmlNodePtr pptr, Z_SRW_diagnostic **recs,
440                                int *num, void *client_data, const char *ns,
441                                int version2)
442 {
443     if (o->direction == ODR_DECODE)
444     {
445         return yaz_srw_decode_diagnostics(o, pptr->children, recs, num, client_data, ns);
446     }
447     else if (o->direction == ODR_ENCODE)
448     {
449         int i;
450         xmlNsPtr ns_diag =
451             xmlNewNs(pptr, BAD_CAST (version2 ?
452                                      YAZ_XMLNS_DIAG_v2 : YAZ_XMLNS_DIAG_v1_1),
453                      BAD_CAST "diag" );
454         for (i = 0; i < *num; i++)
455         {
456             const char *std_diag = "info:srw/diagnostic/1/";
457             const char *ucp_diag = "info:srw/diagnostic/12/";
458             xmlNodePtr rptr = xmlNewChild(pptr, ns_diag,
459                                           BAD_CAST "diagnostic", 0);
460             add_xsd_string(rptr, "uri", (*recs)[i].uri);
461             add_xsd_string(rptr, "details", (*recs)[i].details);
462             if ((*recs)[i].message)
463                 add_xsd_string(rptr, "message", (*recs)[i].message);
464             else if ((*recs)[i].uri )
465             {
466                 if (!strncmp((*recs)[i].uri, std_diag, strlen(std_diag)))
467                 {
468                     int no = atoi((*recs)[i].uri + strlen(std_diag));
469                     const char *message = yaz_diag_srw_str(no);
470                     if (message)
471                         add_xsd_string(rptr, "message", message);
472                 }
473                 else if (!strncmp((*recs)[i].uri, ucp_diag, strlen(ucp_diag)))
474                 {
475                     int no = atoi((*recs)[i].uri + strlen(ucp_diag));
476                     const char *message = yaz_diag_sru_update_str(no);
477                     if (message)
478                         add_xsd_string(rptr, "message", message);
479                 }
480             }
481         }
482     }
483     return 0;
484 }
485
486 static int yaz_srw_term(ODR o, xmlNodePtr pptr, Z_SRW_scanTerm *term,
487                         void *client_data, const char *ns)
488 {
489     if (o->direction == ODR_DECODE)
490     {
491         xmlNodePtr ptr;
492         term->value = 0;
493         term->numberOfRecords = 0;
494         term->displayTerm = 0;
495         term->whereInList = 0;
496         for (ptr = pptr->children; ptr; ptr = ptr->next)
497         {
498             if (yaz_match_xsd_string(ptr, "value", o,  &term->value))
499                 ;
500             else if (yaz_match_xsd_integer(ptr, "numberOfRecords", o,
501                                            &term->numberOfRecords))
502                 ;
503             else if (yaz_match_xsd_string(ptr, "displayTerm", o,
504                                           &term->displayTerm))
505                 ;
506             else
507                 yaz_match_xsd_string(ptr, "whereInList", o, &term->whereInList);
508         }
509     }
510     else if (o->direction == ODR_ENCODE)
511     {
512         xmlNodePtr ptr = pptr;
513         add_xsd_string(ptr, "value", term->value);
514         add_xsd_integer(ptr, "numberOfRecords", term->numberOfRecords);
515         add_xsd_string(ptr, "displayTerm", term->displayTerm);
516         add_xsd_string(ptr, "whereInList", term->whereInList);
517     }
518     return 0;
519 }
520
521 static int yaz_srw_terms(ODR o, xmlNodePtr pptr, Z_SRW_scanTerm **terms,
522                          int *num, void *client_data, const char *ns)
523 {
524     if (o->direction == ODR_DECODE)
525     {
526         int i;
527         xmlNodePtr ptr;
528         *num = 0;
529         for (ptr = pptr->children; ptr; ptr = ptr->next)
530         {
531             if (ptr->type == XML_ELEMENT_NODE &&
532                 !xmlStrcmp(ptr->name, BAD_CAST "term"))
533                 (*num)++;
534         }
535         if (!*num)
536             return 1;
537         *terms = (Z_SRW_scanTerm *) odr_malloc(o, *num * sizeof(**terms));
538         for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next, i++)
539         {
540             if (ptr->type == XML_ELEMENT_NODE &&
541                 !xmlStrcmp(ptr->name, BAD_CAST "term"))
542                 yaz_srw_term(o, ptr, (*terms)+i, client_data, ns);
543         }
544     }
545     else if (o->direction == ODR_ENCODE)
546     {
547         int i;
548         for (i = 0; i < *num; i++)
549         {
550             xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "term", 0);
551             yaz_srw_term(o, rptr, (*terms)+i, client_data, ns);
552         }
553     }
554     return 0;
555 }
556
557 static void encode_echoed_args(xmlNodePtr ptr, Z_SRW_PDU *p, const char *name)
558 {
559     Z_SRW_extra_arg *ea = p->extra_args;
560     if (ea)
561     {
562         xmlNode *p1 = xmlNewChild(ptr, 0, BAD_CAST name, 0);
563         xmlNode *p2 = 0;
564         for (; ea; ea = ea->next)
565         {
566             if (ea->name && ea->name[0] == 'x' && ea->name[1] == '-')
567             {
568                 /* not really according to XSD as of July 2014 */
569                 if (!p2)
570                     p2 = xmlNewChild(p1, 0,
571                                      BAD_CAST "extraRequestData", 0);
572                 /* skip +2: "x-" in element */
573                 add_xsd_string(p2, ea->name + 2, ea->value);
574             }
575             else
576                 add_xsd_string(p1, ea->name, ea->value);
577         }
578     }
579 }
580
581 int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
582                   void *client_data, const char *ns)
583 {
584     xmlNodePtr pptr = (xmlNodePtr) vptr;
585     if (o->direction == ODR_DECODE)
586     {
587         Z_SRW_PDU **p = handler_data;
588         xmlNodePtr method = pptr->children;
589         char *neg_version;
590
591         while (method && method->type == XML_TEXT_NODE)
592             method = method->next;
593
594         if (!method)
595             return -1;
596         if (method->type != XML_ELEMENT_NODE)
597             return -1;
598
599         *p = yaz_srw_get_core_v_2_0(o);
600
601         if (!xmlStrcmp(method->name, BAD_CAST "searchRetrieveRequest"))
602         {
603             xmlNodePtr ptr = method->children;
604             Z_SRW_searchRetrieveRequest *req;
605             char *recordPacking = 0;
606             char *recordXMLEscaping = 0;
607             const char *facetLimit = 0;
608             const char *facetStart = 0;
609             const char *facetSort = 0;
610
611             (*p)->which = Z_SRW_searchRetrieve_request;
612             req = (*p)->u.request = (Z_SRW_searchRetrieveRequest *)
613                 odr_malloc(o, sizeof(*req));
614             req->queryType = "cql";
615             req->query = 0;
616             req->sort_type = Z_SRW_sort_type_none;
617             req->sort.none = 0;
618             req->startRecord = 0;
619             req->maximumRecords = 0;
620             req->recordSchema = 0;
621             req->recordPacking = 0;
622             req->packing = 0;
623             req->recordXPath = 0;
624             req->resultSetTTL = 0;
625             req->stylesheet = 0;
626             req->database = 0;
627
628             for (; ptr; ptr = ptr->next)
629             {
630                 if (yaz_match_xsd_string(ptr, "version", o,
631                                      &(*p)->srw_version))
632                     ;
633                 else if (yaz_match_xsd_string(ptr, "queryType", o,
634                                           &req->queryType))
635                     ;
636                 else if (yaz_match_xsd_string(ptr, "query", o,
637                                           &req->query))
638                     ;
639                 else if (yaz_match_xsd_string(ptr, "pQuery", o,
640                                           &req->query))
641                     req->queryType = "pqf";
642                 else if (yaz_match_xsd_string(ptr, "xQuery", o,
643                                           &req->query))
644                     req->queryType = "xcql";
645                 else if (yaz_match_xsd_integer(ptr, "startRecord", o,
646                                            &req->startRecord))
647                     ;
648                 else if (yaz_match_xsd_integer(ptr, "maximumRecords", o,
649                                            &req->maximumRecords))
650                     ;
651                 else if (yaz_match_xsd_string(ptr, "recordPacking", o,
652                                           &recordPacking))
653                     ;
654                 else if (yaz_match_xsd_string(ptr, "recordXMLEscaping", o,
655                                           &recordXMLEscaping))
656                     ;
657                 else if (yaz_match_xsd_string(ptr, "recordSchema", o,
658                                           &req->recordSchema))
659                     ;
660                 else if (yaz_match_xsd_string(ptr, "recordXPath", o,
661                                           &req->recordXPath))
662                     ;
663                 else if (yaz_match_xsd_integer(ptr, "resultSetTTL", o,
664                                            &req->resultSetTTL))
665                     ;
666                 else if (yaz_match_xsd_string(ptr, "sortKeys", o,
667                                           &req->sort.sortKeys))
668                     req->sort_type = Z_SRW_sort_type_sort;
669                 else if (yaz_match_xsd_string(ptr, "stylesheet", o,
670                                           &req->stylesheet))
671                     ;
672                 else if (yaz_match_xsd_string(ptr, "database", o,
673                                               &req->database))
674                     ;
675                 else if (yaz_match_xsd_string(ptr, "facetLimit", o,
676                                               (char**) &facetLimit))
677                     ;
678                 else if (yaz_match_xsd_string(ptr, "facetStart", o,
679                                               (char**) &facetStart))
680                     ;
681                 else if (yaz_match_xsd_string(ptr, "facetSort", o,
682                                               (char**) &facetSort))
683                     ;
684                 else
685                     ;
686             }
687             if (!req->query)
688             {
689                 /* should put proper diagnostic here */
690                 return -1;
691             }
692             if (!strcmp((*p)->srw_version, "2.0"))
693             {
694                 req->recordPacking = recordXMLEscaping;
695                 req->packing = recordPacking;
696             }
697             else
698             {
699                 req->recordPacking = recordPacking;
700             }
701             yaz_sru_facet_request(o, &req->facetList, &facetLimit, &facetStart,
702                                   &facetSort);
703         }
704         else if (!xmlStrcmp(method->name, BAD_CAST "searchRetrieveResponse"))
705         {
706             xmlNodePtr ptr = method->children;
707             Z_SRW_searchRetrieveResponse *res;
708
709             (*p)->which = Z_SRW_searchRetrieve_response;
710             res = (*p)->u.response = (Z_SRW_searchRetrieveResponse *)
711                 odr_malloc(o, sizeof(*res));
712
713             res->numberOfRecords = 0;
714             res->resultCountPrecision = 0;
715             res->resultSetId = 0;
716             res->resultSetIdleTime = 0;
717             res->records = 0;
718             res->num_records = 0;
719             res->diagnostics = 0;
720             res->num_diagnostics = 0;
721             res->nextRecordPosition = 0;
722             res->facetList = 0;
723             res->suggestions = 0;
724
725             for (; ptr; ptr = ptr->next)
726             {
727                 if (yaz_match_xsd_string(ptr, "version", o,
728                                      &(*p)->srw_version))
729                     ;
730                 else if (yaz_match_xsd_XML_n(ptr, "extraResponseData", o,
731                                          &(*p)->extraResponseData_buf,
732                                          &(*p)->extraResponseData_len))
733                     ;
734                 else if (yaz_match_xsd_integer(ptr, "numberOfRecords", o,
735                                            &res->numberOfRecords))
736                     ;
737                 else if (yaz_match_xsd_string(ptr, "resultCountPrecision", o,
738                                            &res->resultCountPrecision))
739                     ;
740                 else if (yaz_match_xsd_string(ptr, "resultSetId", o,
741                                           &res->resultSetId))
742                     ;
743                 else if (yaz_match_xsd_integer(ptr, "resultSetIdleTime", o,
744                                            &res->resultSetIdleTime))
745                     ;
746                 else if (yaz_match_xsd_integer(ptr, "resultSetTTL", o,
747                                            &res->resultSetIdleTime))
748                     ;
749                 else if (yaz_match_xsd_element(ptr, "records"))
750                     yaz_srw_records(o, ptr, &res->records,
751                                     &res->extra_records,
752                                     &res->num_records, client_data, 0);
753                 else if (yaz_match_xsd_integer(ptr, "nextRecordPosition", o,
754                                            &res->nextRecordPosition))
755                     ;
756                 else if (yaz_match_xsd_element(ptr, "diagnostics"))
757                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
758                                         &res->num_diagnostics,
759                                         client_data, ns, 0);
760                 else if (yaz_match_xsd_element(ptr, "facet_analysis"))
761                     yaz_sru_proxy_decode_facets(o, ptr, &res->facetList);
762                 else if (yaz_match_xsd_element(ptr, "facetedResults"))
763                     yaz_sru_facet_response(o, &res->facetList, ptr);
764             }
765         }
766         else if (!xmlStrcmp(method->name, BAD_CAST "explainRequest"))
767         {
768             Z_SRW_explainRequest *req;
769             xmlNodePtr ptr = method->children;
770
771             (*p)->which = Z_SRW_explain_request;
772             req = (*p)->u.explain_request = (Z_SRW_explainRequest *)
773                 odr_malloc(o, sizeof(*req));
774             req->recordPacking = 0;
775             req->packing = 0;
776             req->database = 0;
777             req->stylesheet = 0;
778             for (; ptr; ptr = ptr->next)
779             {
780                 if (yaz_match_xsd_string(ptr, "version", o,
781                                      &(*p)->srw_version))
782                     ;
783                 else if (yaz_match_xsd_XML_n(ptr, "extraResponseData", o,
784                                          &(*p)->extraResponseData_buf,
785                                          &(*p)->extraResponseData_len))
786                     ;
787                 else if (yaz_match_xsd_string(ptr, "stylesheet", o,
788                                           &req->stylesheet))
789                     ;
790                 else if (yaz_match_xsd_string(ptr, "recordPacking", o,
791                                           &req->recordPacking))
792                     ;
793                 else
794                     yaz_match_xsd_string(ptr, "database", o, &req->database);
795             }
796         }
797         else if (!xmlStrcmp(method->name, BAD_CAST "explainResponse"))
798         {
799             Z_SRW_explainResponse *res;
800             xmlNodePtr ptr = method->children;
801
802             (*p)->which = Z_SRW_explain_response;
803             res = (*p)->u.explain_response = (Z_SRW_explainResponse*)
804                 odr_malloc(o, sizeof(*res));
805             res->diagnostics = 0;
806             res->num_diagnostics = 0;
807             res->record.recordSchema = 0;
808             res->record.recordData_buf = 0;
809             res->record.recordData_len = 0;
810             res->record.recordPosition = 0;
811
812             for (; ptr; ptr = ptr->next)
813             {
814                 if (yaz_match_xsd_string(ptr, "version", o,
815                                      &(*p)->srw_version))
816                     ;
817                 else if (yaz_match_xsd_XML_n(ptr, "extraResponseData", o,
818                                          &(*p)->extraResponseData_buf,
819                                          &(*p)->extraResponseData_len))
820                     ;
821                 else if (yaz_match_xsd_element(ptr, "record"))
822                     yaz_srw_record(o, ptr, &res->record, &res->extra_record,
823                                    client_data, 0);
824                 else if (yaz_match_xsd_element(ptr, "diagnostics"))
825                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
826                                         &res->num_diagnostics,
827                                         client_data, ns, 0);
828                 ;
829             }
830         }
831         else if (!xmlStrcmp(method->name, BAD_CAST "scanRequest"))
832         {
833             Z_SRW_scanRequest *req;
834             xmlNodePtr ptr = method->children;
835
836             (*p)->which = Z_SRW_scan_request;
837             req = (*p)->u.scan_request = (Z_SRW_scanRequest *)
838                 odr_malloc(o, sizeof(*req));
839             req->queryType = "cql";
840             req->scanClause = 0;
841             req->responsePosition = 0;
842             req->maximumTerms = 0;
843             req->stylesheet = 0;
844             req->database = 0;
845
846             for (; ptr; ptr = ptr->next)
847             {
848                 if (yaz_match_xsd_string(ptr, "version", o,
849                                      &(*p)->srw_version))
850                     ;
851                 else if (yaz_match_xsd_XML_n(ptr, "extraResponseData", o,
852                                          &(*p)->extraResponseData_buf,
853                                          &(*p)->extraResponseData_len))
854                     ;
855                 else if (yaz_match_xsd_string(ptr, "scanClause", o,
856                                           &req->scanClause))
857                     ;
858                 else if (yaz_match_xsd_string(ptr, "pScanClause", o,
859                                           &req->scanClause))
860                 {
861                     req->queryType = "pqf";
862                 }
863                 else if (yaz_match_xsd_integer(ptr, "responsePosition", o,
864                                            &req->responsePosition))
865                     ;
866                 else if (yaz_match_xsd_integer(ptr, "maximumTerms", o,
867                                            &req->maximumTerms))
868                     ;
869                 else if (yaz_match_xsd_string(ptr, "stylesheet", o,
870                                           &req->stylesheet))
871                     ;
872                 else
873                     yaz_match_xsd_string(ptr, "database", o, &req->database);
874             }
875         }
876         else if (!xmlStrcmp(method->name, BAD_CAST "scanResponse"))
877         {
878             Z_SRW_scanResponse *res;
879             xmlNodePtr ptr = method->children;
880
881             (*p)->which = Z_SRW_scan_response;
882             res = (*p)->u.scan_response = (Z_SRW_scanResponse *)
883                 odr_malloc(o, sizeof(*res));
884             res->terms = 0;
885             res->num_terms = 0;
886             res->diagnostics = 0;
887             res->num_diagnostics = 0;
888
889             for (; ptr; ptr = ptr->next)
890             {
891                 if (yaz_match_xsd_string(ptr, "version", o,
892                                      &(*p)->srw_version))
893                     ;
894                 else if (yaz_match_xsd_XML_n(ptr, "extraResponseData", o,
895                                          &(*p)->extraResponseData_buf,
896                                          &(*p)->extraResponseData_len))
897                     ;
898                 else if (yaz_match_xsd_element(ptr, "terms"))
899                     yaz_srw_terms(o, ptr, &res->terms,
900                                   &res->num_terms, client_data,
901                                   ns);
902                 else if (yaz_match_xsd_element(ptr, "diagnostics"))
903                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
904                                         &res->num_diagnostics,
905                                         client_data, ns, 0);
906             }
907         }
908         else
909         {
910             *p = 0;
911             return -1;
912         }
913         neg_version = yaz_negotiate_sru_version((*p)->srw_version);
914         if (neg_version)
915             (*p)->srw_version = neg_version;
916     }
917     else if (o->direction == ODR_ENCODE)
918     {
919         Z_SRW_PDU **p = handler_data;
920         xmlNsPtr ns_srw;
921         xmlNodePtr ptr = 0;
922         int version2 = !(*p)->srw_version ||
923             strcmp((*p)->srw_version, "2.") > 0;
924         if ((*p)->which == Z_SRW_searchRetrieve_request)
925         {
926             Z_SRW_searchRetrieveRequest *req = (*p)->u.request;
927             const char *queryType = req->queryType;
928             if (version2)
929                 ns = "http://docs.oasis-open.org/ns/search-ws/sruRequest";
930             ptr = xmlNewChild(pptr, 0, BAD_CAST "searchRetrieveRequest", 0);
931             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
932             xmlSetNs(ptr, ns_srw);
933
934             if (!version2)
935                 add_xsd_string(ptr, "version", (*p)->srw_version);
936             if (version2)
937             {
938                 add_xsd_string(ptr, "query", req->query);
939             }
940             else
941             {
942                 if (!queryType || !strcmp(queryType, "cql"))
943                     add_xsd_string(ptr, "query", req->query);
944                 else if (!strcmp(queryType, "xcql"))
945                     add_xsd_string(ptr, "xQuery", req->query);
946                 else if (!strcmp(queryType, "pqf"))
947                     add_xsd_string(ptr, "pQuery", req->query);
948                 queryType = 0;
949             }
950             add_xsd_integer(ptr, "startRecord", req->startRecord);
951             add_xsd_integer(ptr, "maximumRecords", req->maximumRecords);
952             if (version2)
953                 add_xsd_string(ptr, "recordXMLEscaping", req->recordPacking);
954             else
955                 add_xsd_string(ptr, "recordPacking", req->recordPacking);
956             add_xsd_string(ptr, "recordSchema", req->recordSchema);
957             add_xsd_string(ptr, "recordXPath", req->recordXPath);
958             add_xsd_integer(ptr, "resultSetTTL", req->resultSetTTL);
959             add_xsd_string(ptr, "stylesheet", req->stylesheet);
960             add_xsd_string(ptr, "queryType", queryType);
961             switch (req->sort_type)
962             {
963             case Z_SRW_sort_type_none:
964                 break;
965             case Z_SRW_sort_type_sort:
966                 add_xsd_string(ptr, "sortKeys", req->sort.sortKeys);
967                 break;
968             case Z_SRW_sort_type_xSort:
969                 add_xsd_string(ptr, "xSortKeys", req->sort.xSortKeys);
970                 break;
971             }
972             /* still unsupported are: renderedBy, httpAccept, responseType */
973             add_xsd_string(ptr, "database", req->database);
974             if (version2)
975                 add_xsd_string(ptr, "recordPacking", req->packing);
976             {
977                 const char *limit = 0;
978                 const char *start = 0;
979                 const char *sort = 0;
980                 yaz_sru_facet_request(o, &req->facetList, &limit, &start,
981                                       &sort);
982                 add_xsd_string(ptr, "facetLimit", limit);
983                 add_xsd_string(ptr, "facetStart", start);
984                 add_xsd_string(ptr, "facetSort", sort);
985             }
986         }
987         else if ((*p)->which == Z_SRW_searchRetrieve_response)
988         {
989             Z_SRW_searchRetrieveResponse *res = (*p)->u.response;
990             if (version2)
991                 ns = "http://docs.oasis-open.org/ns/search-ws/sruResponse";
992             ptr = xmlNewChild(pptr, 0, BAD_CAST "searchRetrieveResponse", 0);
993             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
994             xmlSetNs(ptr, ns_srw);
995
996             if (!version2)
997                 add_xsd_string(ptr, "version", (*p)->srw_version);
998             add_xsd_integer(ptr, "numberOfRecords", res->numberOfRecords);
999             add_xsd_string(ptr, "resultSetId", res->resultSetId);
1000             if (!version2)
1001                 add_xsd_integer(ptr, "resultSetIdleTime",
1002                                 res->resultSetIdleTime);
1003             if (res->num_records)
1004             {
1005                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "records", 0);
1006                 yaz_srw_records(o, rptr, &res->records, &res->extra_records,
1007                                 &res->num_records,
1008                                 client_data, version2);
1009             }
1010             add_xsd_integer(ptr, "nextRecordPosition",
1011                             res->nextRecordPosition);
1012             encode_echoed_args(ptr, *p, "echoedSearchRetrieveRequest");
1013             if (res->num_diagnostics)
1014             {
1015                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
1016                                               0);
1017                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1018                                     &res->num_diagnostics, client_data, ns,
1019                                     version2);
1020             }
1021             if (version2)
1022             {
1023                 if (ptr && (*p)->extraResponseData_len)
1024                     add_XML_n(ptr, "extraResponseData",
1025                               (*p)->extraResponseData_buf,
1026                               (*p)->extraResponseData_len, ns_srw);
1027                 add_xsd_integer(ptr, "resultSetTTL", res->resultSetIdleTime);
1028                 add_xsd_string(ptr, "resultCountPrecision",
1029                                res->resultCountPrecision);
1030                 yaz_sru_facet_response(o, &res->facetList, ptr);
1031                 return 0; /* so we don't make extra response data twice */
1032             }
1033         }
1034         else if ((*p)->which == Z_SRW_explain_request)
1035         {
1036             Z_SRW_explainRequest *req = (*p)->u.explain_request;
1037             if (version2)
1038                 ns = "http://docs.oasis-open.org/ns/search-ws/sruRequest";
1039             ptr = xmlNewChild(pptr, 0, BAD_CAST "explainRequest", 0);
1040             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1041             xmlSetNs(ptr, ns_srw);
1042
1043             if (!version2)
1044                 add_xsd_string(ptr, "version", (*p)->srw_version);
1045             if (version2)
1046             {
1047                 add_xsd_string(ptr, "recordXMLEscaping", req->recordPacking);
1048                 add_xsd_string(ptr, "recordPacking", req->packing);
1049             }
1050             else
1051                 add_xsd_string(ptr, "recordPacking", req->recordPacking);
1052             add_xsd_string(ptr, "stylesheet", req->stylesheet);
1053             add_xsd_string(ptr, "database", req->database);
1054         }
1055         else if ((*p)->which == Z_SRW_explain_response)
1056         {
1057             Z_SRW_explainResponse *res = (*p)->u.explain_response;
1058             if (version2)
1059                 ns = "http://docs.oasis-open.org/ns/search-ws/sruResponse";
1060             ptr = xmlNewChild(pptr, 0, BAD_CAST "explainResponse", 0);
1061             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1062             xmlSetNs(ptr, ns_srw);
1063
1064             add_xsd_string(ptr, "version", (*p)->srw_version);
1065             if (1)
1066             {
1067                 xmlNodePtr ptr1 = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
1068                 yaz_srw_record(o, ptr1, &res->record, &res->extra_record,
1069                                client_data, version2);
1070             }
1071             encode_echoed_args(ptr, *p, "echoedExplainRequest");
1072             if (res->num_diagnostics)
1073             {
1074                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
1075                                               0);
1076                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1077                                     &res->num_diagnostics, client_data, ns,
1078                                     version2);
1079             }
1080         }
1081         else if ((*p)->which == Z_SRW_scan_request)
1082         {
1083             Z_SRW_scanRequest *req = (*p)->u.scan_request;
1084             const char *queryType = req->queryType;
1085             if (version2)
1086                 ns = "http://docs.oasis-open.org/ns/search-ws/scan";
1087             ptr = xmlNewChild(pptr, 0, BAD_CAST "scanRequest", 0);
1088             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1089             xmlSetNs(ptr, ns_srw);
1090
1091             if (!version2)
1092                 add_xsd_string(ptr, "version", (*p)->srw_version);
1093
1094             if (version2)
1095             {
1096                 if (queryType && strcmp(queryType, "cql"))
1097                     add_xsd_string(ptr, "queryType", queryType);
1098                 add_xsd_string(ptr, "scanClause", req->scanClause);
1099             }
1100             else
1101             {
1102                 if (!queryType || !strcmp(queryType, "cql"))
1103                     add_xsd_string(ptr, "scanClause", req->scanClause);
1104                 else if (!strcmp(queryType, "pqf"))
1105                     add_xsd_string(ptr, "pScanClause", req->scanClause);
1106             }
1107             add_xsd_integer(ptr, "responsePosition", req->responsePosition);
1108             add_xsd_integer(ptr, "maximumTerms", req->maximumTerms);
1109             add_xsd_string(ptr, "stylesheet", req->stylesheet);
1110             add_xsd_string(ptr, "database", req->database);
1111         }
1112         else if ((*p)->which == Z_SRW_scan_response)
1113         {
1114             Z_SRW_scanResponse *res = (*p)->u.scan_response;
1115             if (version2)
1116                 ns = "http://docs.oasis-open.org/ns/search-ws/scan";
1117             ptr = xmlNewChild(pptr, 0, BAD_CAST "scanResponse", 0);
1118             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1119             xmlSetNs(ptr, ns_srw);
1120
1121             if (!version2)
1122                 add_xsd_string(ptr, "version", (*p)->srw_version);
1123             if (res->num_terms)
1124             {
1125                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "terms", 0);
1126                 yaz_srw_terms(o, rptr, &res->terms, &res->num_terms,
1127                               client_data, ns);
1128             }
1129             if (res->num_diagnostics)
1130             {
1131                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
1132                                               0);
1133                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1134                                     &res->num_diagnostics, client_data, ns,
1135                                     version2);
1136             }
1137         }
1138         else
1139             return -1;
1140         if (ptr && (*p)->extraResponseData_len)
1141             add_XML_n(ptr, "extraResponseData",
1142                       (*p)->extraResponseData_buf,
1143                       (*p)->extraResponseData_len, ns_srw);
1144
1145
1146     }
1147     return 0;
1148 }
1149
1150 int yaz_ucp_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
1151                   void *client_data, const char *ns_ucp_str)
1152 {
1153     xmlNodePtr pptr = (xmlNodePtr) vptr;
1154     const char *ns_srw_str = YAZ_XMLNS_SRU_v1_1;
1155     if (o->direction == ODR_DECODE)
1156     {
1157         Z_SRW_PDU **p = handler_data;
1158         xmlNodePtr method = pptr->children;
1159
1160         while (method && method->type == XML_TEXT_NODE)
1161             method = method->next;
1162
1163         if (!method)
1164             return -1;
1165         if (method->type != XML_ELEMENT_NODE)
1166             return -1;
1167
1168         *p = yaz_srw_get_core_v_2_0(o);
1169
1170         if (!xmlStrcmp(method->name, BAD_CAST "updateRequest"))
1171         {
1172             xmlNodePtr ptr = method->children;
1173             Z_SRW_updateRequest *req;
1174             char *oper = 0;
1175
1176             (*p)->which = Z_SRW_update_request;
1177             req = (*p)->u.update_request = (Z_SRW_updateRequest *)
1178                 odr_malloc(o, sizeof(*req));
1179             req->database = 0;
1180             req->operation = 0;
1181             req->recordId = 0;
1182             req->recordVersions = 0;
1183             req->num_recordVersions = 0;
1184             req->record = 0;
1185             req->extra_record = 0;
1186             req->extraRequestData_buf = 0;
1187             req->extraRequestData_len = 0;
1188             req->stylesheet = 0;
1189
1190             for (; ptr; ptr = ptr->next)
1191             {
1192                 if (yaz_match_xsd_string(ptr, "version", o,
1193                                      &(*p)->srw_version))
1194                     ;
1195                 else if (yaz_match_xsd_string(ptr, "action", o,
1196                                           &oper)){
1197                     if (oper)
1198                     {
1199                         if (!strcmp(oper, "info:srw/action/1/delete"))
1200                             req->operation = "delete";
1201                         else if (!strcmp(oper,"info:srw/action/1/replace" ))
1202                             req->operation = "replace";
1203                         else if (!strcmp(oper, "info:srw/action/1/create"))
1204                             req->operation = "insert";
1205                     }
1206                 }
1207                 else if (yaz_match_xsd_string(ptr, "recordIdentifier", o,
1208                                           &req->recordId))
1209                     ;
1210                 else if (yaz_match_xsd_element(ptr, "recordVersions" ) )
1211                     yaz_srw_versions( o, ptr, &req->recordVersions,
1212                                       &req->num_recordVersions, client_data,
1213                                       ns_ucp_str);
1214                 else if (yaz_match_xsd_element(ptr, "record"))
1215                 {
1216                     req->record = yaz_srw_get_record(o);
1217                     yaz_srw_record(o, ptr, req->record, &req->extra_record,
1218                                    client_data, 0);
1219                 }
1220                 else if (yaz_match_xsd_string(ptr, "stylesheet", o,
1221                                           &req->stylesheet))
1222                     ;
1223                 else
1224                     yaz_match_xsd_string(ptr, "database", o, &req->database);
1225             }
1226         }
1227         else if (!xmlStrcmp(method->name, BAD_CAST "updateResponse"))
1228         {
1229             xmlNodePtr ptr = method->children;
1230             Z_SRW_updateResponse *res;
1231
1232             (*p)->which = Z_SRW_update_response;
1233             res = (*p)->u.update_response = (Z_SRW_updateResponse *)
1234                 odr_malloc(o, sizeof(*res));
1235
1236             res->operationStatus = 0;
1237             res->recordId = 0;
1238             res->recordVersions = 0;
1239             res->num_recordVersions = 0;
1240             res->diagnostics = 0;
1241             res->num_diagnostics = 0;
1242             res->record = 0;
1243             res->extra_record = 0;
1244             res->extraResponseData_buf = 0;
1245             res->extraResponseData_len = 0;
1246
1247             for (; ptr; ptr = ptr->next)
1248             {
1249                 if (yaz_match_xsd_string(ptr, "version", o,
1250                                      &(*p)->srw_version))
1251                     ;
1252                 else if (yaz_match_xsd_string(ptr, "operationStatus", o,
1253                                           &res->operationStatus ))
1254                     ;
1255                 else if (yaz_match_xsd_string(ptr, "recordIdentifier", o,
1256                                           &res->recordId))
1257                     ;
1258                 else if (yaz_match_xsd_element(ptr, "recordVersions" ))
1259                     yaz_srw_versions(o, ptr, &res->recordVersions,
1260                                      &res->num_recordVersions,
1261                                      client_data, ns_ucp_str);
1262                 else if (yaz_match_xsd_element(ptr, "record"))
1263                 {
1264                     res->record = yaz_srw_get_record(o);
1265                     yaz_srw_record(o, ptr, res->record, &res->extra_record,
1266                                    client_data, 0);
1267                 }
1268                 else if (yaz_match_xsd_element(ptr, "diagnostics"))
1269                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
1270                                         &res->num_diagnostics,
1271                                         client_data, ns_ucp_str, 0);
1272             }
1273         }
1274         else if (!xmlStrcmp(method->name, BAD_CAST "explainUpdateRequest"))
1275         {
1276         }
1277         else if (!xmlStrcmp(method->name, BAD_CAST "explainUpdateResponse"))
1278         {
1279         }
1280         else
1281         {
1282             *p = 0;
1283             return -1;
1284         }
1285     }
1286     else if (o->direction == ODR_ENCODE)
1287     {
1288         Z_SRW_PDU **p = handler_data;
1289         xmlNsPtr ns_ucp, ns_srw;
1290
1291         if ((*p)->which == Z_SRW_update_request)
1292         {
1293             Z_SRW_updateRequest *req = (*p)->u.update_request;
1294             xmlNodePtr ptr = xmlNewChild(pptr, 0, BAD_CAST "updateRequest", 0);
1295             ns_ucp = xmlNewNs(ptr, BAD_CAST ns_ucp_str, BAD_CAST "zu");
1296             xmlSetNs(ptr, ns_ucp);
1297             ns_srw = xmlNewNs(ptr, BAD_CAST ns_srw_str, BAD_CAST "zs");
1298
1299             add_xsd_string_ns(ptr, "version", (*p)->srw_version, ns_srw);
1300             add_xsd_string(ptr, "action", req->operation);
1301             add_xsd_string(ptr, "recordIdentifier", req->recordId );
1302             if (req->recordVersions)
1303                 yaz_srw_versions( o, ptr, &req->recordVersions,
1304                                   &req->num_recordVersions,
1305                                   client_data, ns_ucp_str);
1306             if (req->record && req->record->recordData_len)
1307             {
1308                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
1309                 xmlSetNs(rptr, ns_srw);
1310                 yaz_srw_record(o, rptr, req->record, &req->extra_record,
1311                                client_data, 0);
1312             }
1313             if (req->extraRequestData_len)
1314             {
1315                 add_XML_n(ptr, "extraRequestData",
1316                           req->extraRequestData_buf,
1317                           req->extraRequestData_len, ns_srw);
1318             }
1319             add_xsd_string(ptr, "stylesheet", req->stylesheet);
1320             add_xsd_string(ptr, "database", req->database);
1321         }
1322         else if ((*p)->which == Z_SRW_update_response)
1323         {
1324             Z_SRW_updateResponse *res = (*p)->u.update_response;
1325             xmlNodePtr ptr = xmlNewChild(pptr, 0, (xmlChar *)
1326                                          "updateResponse", 0);
1327             ns_ucp = xmlNewNs(ptr, BAD_CAST ns_ucp_str, BAD_CAST "zu");
1328             xmlSetNs(ptr, ns_ucp);
1329             ns_srw = xmlNewNs(ptr, BAD_CAST ns_srw_str, BAD_CAST "zs");
1330
1331             add_xsd_string_ns(ptr, "version", (*p)->srw_version, ns_srw);
1332             add_xsd_string(ptr, "operationStatus", res->operationStatus );
1333             add_xsd_string(ptr, "recordIdentifier", res->recordId );
1334             if (res->recordVersions)
1335                 yaz_srw_versions(o, ptr, &res->recordVersions,
1336                                  &res->num_recordVersions,
1337                                  client_data, ns_ucp_str);
1338             if (res->record && res->record->recordData_len)
1339             {
1340                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
1341                 xmlSetNs(rptr, ns_srw);
1342                 yaz_srw_record(o, rptr, res->record, &res->extra_record,
1343                                client_data, 0);
1344             }
1345             if (res->num_diagnostics)
1346             {
1347                 xmlNsPtr ns_diag =
1348                     xmlNewNs(pptr, BAD_CAST YAZ_XMLNS_DIAG_v1_1,
1349                              BAD_CAST "diag" );
1350
1351                 xmlNodePtr rptr = xmlNewChild(ptr, ns_diag, BAD_CAST "diagnostics", 0);
1352                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1353                                     &res->num_diagnostics, client_data,
1354                                     ns_ucp_str, 0);
1355             }
1356             if (res->extraResponseData_len)
1357                 add_XML_n(ptr, "extraResponseData",
1358                           res->extraResponseData_buf,
1359                           res->extraResponseData_len, ns_srw);
1360         }
1361         else
1362             return -1;
1363     }
1364     return 0;
1365 }
1366
1367 #endif
1368
1369
1370 /*
1371  * Local variables:
1372  * c-basic-offset: 4
1373  * c-file-style: "Stroustrup"
1374  * indent-tabs-mode: nil
1375  * End:
1376  * vim: shiftwidth=4 tabstop=8 expandtab
1377  */
1378