echoedSearchRetrieveRequest for explain as well YAZ-776
[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 int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
558                   void *client_data, const char *ns)
559 {
560     xmlNodePtr pptr = (xmlNodePtr) vptr;
561     if (o->direction == ODR_DECODE)
562     {
563         Z_SRW_PDU **p = handler_data;
564         xmlNodePtr method = pptr->children;
565         char *neg_version;
566
567         while (method && method->type == XML_TEXT_NODE)
568             method = method->next;
569
570         if (!method)
571             return -1;
572         if (method->type != XML_ELEMENT_NODE)
573             return -1;
574
575         *p = yaz_srw_get_core_v_2_0(o);
576
577         if (!xmlStrcmp(method->name, BAD_CAST "searchRetrieveRequest"))
578         {
579             xmlNodePtr ptr = method->children;
580             Z_SRW_searchRetrieveRequest *req;
581             char *recordPacking = 0;
582             char *recordXMLEscaping = 0;
583             const char *facetLimit = 0;
584             const char *facetStart = 0;
585             const char *facetSort = 0;
586
587             (*p)->which = Z_SRW_searchRetrieve_request;
588             req = (*p)->u.request = (Z_SRW_searchRetrieveRequest *)
589                 odr_malloc(o, sizeof(*req));
590             req->queryType = "cql";
591             req->query = 0;
592             req->sort_type = Z_SRW_sort_type_none;
593             req->sort.none = 0;
594             req->startRecord = 0;
595             req->maximumRecords = 0;
596             req->recordSchema = 0;
597             req->recordPacking = 0;
598             req->packing = 0;
599             req->recordXPath = 0;
600             req->resultSetTTL = 0;
601             req->stylesheet = 0;
602             req->database = 0;
603
604             for (; ptr; ptr = ptr->next)
605             {
606                 if (yaz_match_xsd_string(ptr, "version", o,
607                                      &(*p)->srw_version))
608                     ;
609                 else if (yaz_match_xsd_string(ptr, "queryType", o,
610                                           &req->queryType))
611                     ;
612                 else if (yaz_match_xsd_string(ptr, "query", o,
613                                           &req->query))
614                     ;
615                 else if (yaz_match_xsd_string(ptr, "pQuery", o,
616                                           &req->query))
617                     req->queryType = "pqf";
618                 else if (yaz_match_xsd_string(ptr, "xQuery", o,
619                                           &req->query))
620                     req->queryType = "xcql";
621                 else if (yaz_match_xsd_integer(ptr, "startRecord", o,
622                                            &req->startRecord))
623                     ;
624                 else if (yaz_match_xsd_integer(ptr, "maximumRecords", o,
625                                            &req->maximumRecords))
626                     ;
627                 else if (yaz_match_xsd_string(ptr, "recordPacking", o,
628                                           &recordPacking))
629                     ;
630                 else if (yaz_match_xsd_string(ptr, "recordXMLEscaping", o,
631                                           &recordXMLEscaping))
632                     ;
633                 else if (yaz_match_xsd_string(ptr, "recordSchema", o,
634                                           &req->recordSchema))
635                     ;
636                 else if (yaz_match_xsd_string(ptr, "recordXPath", o,
637                                           &req->recordXPath))
638                     ;
639                 else if (yaz_match_xsd_integer(ptr, "resultSetTTL", o,
640                                            &req->resultSetTTL))
641                     ;
642                 else if (yaz_match_xsd_string(ptr, "sortKeys", o,
643                                           &req->sort.sortKeys))
644                     req->sort_type = Z_SRW_sort_type_sort;
645                 else if (yaz_match_xsd_string(ptr, "stylesheet", o,
646                                           &req->stylesheet))
647                     ;
648                 else if (yaz_match_xsd_string(ptr, "database", o,
649                                               &req->database))
650                     ;
651                 else if (yaz_match_xsd_string(ptr, "facetLimit", o,
652                                               (char**) &facetLimit))
653                     ;
654                 else if (yaz_match_xsd_string(ptr, "facetStart", o,
655                                               (char**) &facetStart))
656                     ;
657                 else if (yaz_match_xsd_string(ptr, "facetSort", o,
658                                               (char**) &facetSort))
659                     ;
660                 else
661                     ;
662             }
663             if (!req->query)
664             {
665                 /* should put proper diagnostic here */
666                 return -1;
667             }
668             if (!strcmp((*p)->srw_version, "2.0"))
669             {
670                 req->recordPacking = recordXMLEscaping;
671                 req->packing = recordPacking;
672             }
673             else
674             {
675                 req->recordPacking = recordPacking;
676             }
677             yaz_sru_facet_request(o, &req->facetList, &facetLimit, &facetStart,
678                                   &facetSort);
679         }
680         else if (!xmlStrcmp(method->name, BAD_CAST "searchRetrieveResponse"))
681         {
682             xmlNodePtr ptr = method->children;
683             Z_SRW_searchRetrieveResponse *res;
684
685             (*p)->which = Z_SRW_searchRetrieve_response;
686             res = (*p)->u.response = (Z_SRW_searchRetrieveResponse *)
687                 odr_malloc(o, sizeof(*res));
688
689             res->numberOfRecords = 0;
690             res->resultCountPrecision = 0;
691             res->resultSetId = 0;
692             res->resultSetIdleTime = 0;
693             res->records = 0;
694             res->num_records = 0;
695             res->diagnostics = 0;
696             res->num_diagnostics = 0;
697             res->nextRecordPosition = 0;
698             res->facetList = 0;
699             res->suggestions = 0;
700
701             for (; ptr; ptr = ptr->next)
702             {
703                 if (yaz_match_xsd_string(ptr, "version", o,
704                                      &(*p)->srw_version))
705                     ;
706                 else if (yaz_match_xsd_XML_n(ptr, "extraResponseData", o,
707                                          &(*p)->extraResponseData_buf,
708                                          &(*p)->extraResponseData_len))
709                     ;
710                 else if (yaz_match_xsd_integer(ptr, "numberOfRecords", o,
711                                            &res->numberOfRecords))
712                     ;
713                 else if (yaz_match_xsd_string(ptr, "resultCountPrecision", o,
714                                            &res->resultCountPrecision))
715                     ;
716                 else if (yaz_match_xsd_string(ptr, "resultSetId", o,
717                                           &res->resultSetId))
718                     ;
719                 else if (yaz_match_xsd_integer(ptr, "resultSetIdleTime", o,
720                                            &res->resultSetIdleTime))
721                     ;
722                 else if (yaz_match_xsd_integer(ptr, "resultSetTTL", o,
723                                            &res->resultSetIdleTime))
724                     ;
725                 else if (yaz_match_xsd_element(ptr, "records"))
726                     yaz_srw_records(o, ptr, &res->records,
727                                     &res->extra_records,
728                                     &res->num_records, client_data, 0);
729                 else if (yaz_match_xsd_integer(ptr, "nextRecordPosition", o,
730                                            &res->nextRecordPosition))
731                     ;
732                 else if (yaz_match_xsd_element(ptr, "diagnostics"))
733                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
734                                         &res->num_diagnostics,
735                                         client_data, ns, 0);
736                 else if (yaz_match_xsd_element(ptr, "facet_analysis"))
737                     yaz_sru_proxy_decode_facets(o, ptr, &res->facetList);
738                 else if (yaz_match_xsd_element(ptr, "facetedResults"))
739                     yaz_sru_facet_response(o, &res->facetList, ptr);
740             }
741         }
742         else if (!xmlStrcmp(method->name, BAD_CAST "explainRequest"))
743         {
744             Z_SRW_explainRequest *req;
745             xmlNodePtr ptr = method->children;
746
747             (*p)->which = Z_SRW_explain_request;
748             req = (*p)->u.explain_request = (Z_SRW_explainRequest *)
749                 odr_malloc(o, sizeof(*req));
750             req->recordPacking = 0;
751             req->packing = 0;
752             req->database = 0;
753             req->stylesheet = 0;
754             for (; ptr; ptr = ptr->next)
755             {
756                 if (yaz_match_xsd_string(ptr, "version", o,
757                                      &(*p)->srw_version))
758                     ;
759                 else if (yaz_match_xsd_XML_n(ptr, "extraResponseData", o,
760                                          &(*p)->extraResponseData_buf,
761                                          &(*p)->extraResponseData_len))
762                     ;
763                 else if (yaz_match_xsd_string(ptr, "stylesheet", o,
764                                           &req->stylesheet))
765                     ;
766                 else if (yaz_match_xsd_string(ptr, "recordPacking", o,
767                                           &req->recordPacking))
768                     ;
769                 else
770                     yaz_match_xsd_string(ptr, "database", o, &req->database);
771             }
772         }
773         else if (!xmlStrcmp(method->name, BAD_CAST "explainResponse"))
774         {
775             Z_SRW_explainResponse *res;
776             xmlNodePtr ptr = method->children;
777
778             (*p)->which = Z_SRW_explain_response;
779             res = (*p)->u.explain_response = (Z_SRW_explainResponse*)
780                 odr_malloc(o, sizeof(*res));
781             res->diagnostics = 0;
782             res->num_diagnostics = 0;
783             res->record.recordSchema = 0;
784             res->record.recordData_buf = 0;
785             res->record.recordData_len = 0;
786             res->record.recordPosition = 0;
787
788             for (; ptr; ptr = ptr->next)
789             {
790                 if (yaz_match_xsd_string(ptr, "version", o,
791                                      &(*p)->srw_version))
792                     ;
793                 else if (yaz_match_xsd_XML_n(ptr, "extraResponseData", o,
794                                          &(*p)->extraResponseData_buf,
795                                          &(*p)->extraResponseData_len))
796                     ;
797                 else if (yaz_match_xsd_element(ptr, "record"))
798                     yaz_srw_record(o, ptr, &res->record, &res->extra_record,
799                                    client_data, 0);
800                 else if (yaz_match_xsd_element(ptr, "diagnostics"))
801                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
802                                         &res->num_diagnostics,
803                                         client_data, ns, 0);
804                 ;
805             }
806         }
807         else if (!xmlStrcmp(method->name, BAD_CAST "scanRequest"))
808         {
809             Z_SRW_scanRequest *req;
810             xmlNodePtr ptr = method->children;
811
812             (*p)->which = Z_SRW_scan_request;
813             req = (*p)->u.scan_request = (Z_SRW_scanRequest *)
814                 odr_malloc(o, sizeof(*req));
815             req->queryType = "cql";
816             req->scanClause = 0;
817             req->responsePosition = 0;
818             req->maximumTerms = 0;
819             req->stylesheet = 0;
820             req->database = 0;
821
822             for (; ptr; ptr = ptr->next)
823             {
824                 if (yaz_match_xsd_string(ptr, "version", o,
825                                      &(*p)->srw_version))
826                     ;
827                 else if (yaz_match_xsd_XML_n(ptr, "extraResponseData", o,
828                                          &(*p)->extraResponseData_buf,
829                                          &(*p)->extraResponseData_len))
830                     ;
831                 else if (yaz_match_xsd_string(ptr, "scanClause", o,
832                                           &req->scanClause))
833                     ;
834                 else if (yaz_match_xsd_string(ptr, "pScanClause", o,
835                                           &req->scanClause))
836                 {
837                     req->queryType = "pqf";
838                 }
839                 else if (yaz_match_xsd_integer(ptr, "responsePosition", o,
840                                            &req->responsePosition))
841                     ;
842                 else if (yaz_match_xsd_integer(ptr, "maximumTerms", o,
843                                            &req->maximumTerms))
844                     ;
845                 else if (yaz_match_xsd_string(ptr, "stylesheet", o,
846                                           &req->stylesheet))
847                     ;
848                 else
849                     yaz_match_xsd_string(ptr, "database", o, &req->database);
850             }
851         }
852         else if (!xmlStrcmp(method->name, BAD_CAST "scanResponse"))
853         {
854             Z_SRW_scanResponse *res;
855             xmlNodePtr ptr = method->children;
856
857             (*p)->which = Z_SRW_scan_response;
858             res = (*p)->u.scan_response = (Z_SRW_scanResponse *)
859                 odr_malloc(o, sizeof(*res));
860             res->terms = 0;
861             res->num_terms = 0;
862             res->diagnostics = 0;
863             res->num_diagnostics = 0;
864
865             for (; ptr; ptr = ptr->next)
866             {
867                 if (yaz_match_xsd_string(ptr, "version", o,
868                                      &(*p)->srw_version))
869                     ;
870                 else if (yaz_match_xsd_XML_n(ptr, "extraResponseData", o,
871                                          &(*p)->extraResponseData_buf,
872                                          &(*p)->extraResponseData_len))
873                     ;
874                 else if (yaz_match_xsd_element(ptr, "terms"))
875                     yaz_srw_terms(o, ptr, &res->terms,
876                                   &res->num_terms, client_data,
877                                   ns);
878                 else if (yaz_match_xsd_element(ptr, "diagnostics"))
879                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
880                                         &res->num_diagnostics,
881                                         client_data, ns, 0);
882             }
883         }
884         else
885         {
886             *p = 0;
887             return -1;
888         }
889         neg_version = yaz_negotiate_sru_version((*p)->srw_version);
890         if (neg_version)
891             (*p)->srw_version = neg_version;
892     }
893     else if (o->direction == ODR_ENCODE)
894     {
895         Z_SRW_PDU **p = handler_data;
896         xmlNsPtr ns_srw;
897         xmlNodePtr ptr = 0;
898         int version2 = !(*p)->srw_version ||
899             strcmp((*p)->srw_version, "2.") > 0;
900         if ((*p)->which == Z_SRW_searchRetrieve_request)
901         {
902             Z_SRW_searchRetrieveRequest *req = (*p)->u.request;
903             const char *queryType = req->queryType;
904             if (version2)
905                 ns = "http://docs.oasis-open.org/ns/search-ws/sruRequest";
906             ptr = xmlNewChild(pptr, 0, BAD_CAST "searchRetrieveRequest", 0);
907             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
908             xmlSetNs(ptr, ns_srw);
909
910             if (!version2)
911                 add_xsd_string(ptr, "version", (*p)->srw_version);
912             if (version2)
913             {
914                 add_xsd_string(ptr, "query", req->query);
915             }
916             else
917             {
918                 if (!queryType || !strcmp(queryType, "cql"))
919                     add_xsd_string(ptr, "query", req->query);
920                 else if (!strcmp(queryType, "xcql"))
921                     add_xsd_string(ptr, "xQuery", req->query);
922                 else if (!strcmp(queryType, "pqf"))
923                     add_xsd_string(ptr, "pQuery", req->query);
924                 queryType = 0;
925             }
926             add_xsd_integer(ptr, "startRecord", req->startRecord);
927             add_xsd_integer(ptr, "maximumRecords", req->maximumRecords);
928             if (version2)
929                 add_xsd_string(ptr, "recordXMLEscaping", req->recordPacking);
930             else
931                 add_xsd_string(ptr, "recordPacking", req->recordPacking);
932             add_xsd_string(ptr, "recordSchema", req->recordSchema);
933             add_xsd_string(ptr, "recordXPath", req->recordXPath);
934             add_xsd_integer(ptr, "resultSetTTL", req->resultSetTTL);
935             add_xsd_string(ptr, "stylesheet", req->stylesheet);
936             add_xsd_string(ptr, "queryType", queryType);
937             switch (req->sort_type)
938             {
939             case Z_SRW_sort_type_none:
940                 break;
941             case Z_SRW_sort_type_sort:
942                 add_xsd_string(ptr, "sortKeys", req->sort.sortKeys);
943                 break;
944             case Z_SRW_sort_type_xSort:
945                 add_xsd_string(ptr, "xSortKeys", req->sort.xSortKeys);
946                 break;
947             }
948             /* still unsupported are: renderedBy, httpAccept, responseType */
949             add_xsd_string(ptr, "database", req->database);
950             if (version2)
951                 add_xsd_string(ptr, "recordPacking", req->packing);
952             {
953                 const char *limit = 0;
954                 const char *start = 0;
955                 const char *sort = 0;
956                 yaz_sru_facet_request(o, &req->facetList, &limit, &start,
957                                       &sort);
958                 add_xsd_string(ptr, "facetLimit", limit);
959                 add_xsd_string(ptr, "facetStart", start);
960                 add_xsd_string(ptr, "facetSort", sort);
961             }
962         }
963         else if ((*p)->which == Z_SRW_searchRetrieve_response)
964         {
965             Z_SRW_searchRetrieveResponse *res = (*p)->u.response;
966             if (version2)
967                 ns = "http://docs.oasis-open.org/ns/search-ws/sruResponse";
968             ptr = xmlNewChild(pptr, 0, BAD_CAST "searchRetrieveResponse", 0);
969             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
970             xmlSetNs(ptr, ns_srw);
971
972             if (!version2)
973                 add_xsd_string(ptr, "version", (*p)->srw_version);
974             add_xsd_integer(ptr, "numberOfRecords", res->numberOfRecords);
975             add_xsd_string(ptr, "resultSetId", res->resultSetId);
976             if (!version2)
977                 add_xsd_integer(ptr, "resultSetIdleTime",
978                                 res->resultSetIdleTime);
979             if (res->num_records)
980             {
981                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "records", 0);
982                 yaz_srw_records(o, rptr, &res->records, &res->extra_records,
983                                 &res->num_records,
984                                 client_data, version2);
985             }
986             add_xsd_integer(ptr, "nextRecordPosition",
987                             res->nextRecordPosition);
988             if ((*p)->extra_args)
989             {
990                 xmlNode *p1 =
991                     xmlNewChild(ptr, 0, BAD_CAST "echoedSearchRetrieveRequest",
992                                 0);
993                 Z_SRW_extra_arg *ea = (*p)->extra_args;
994                 for (; ea; ea = ea->next)
995                     add_xsd_string(p1, ea->name, ea->value);
996
997             }
998             if (res->num_diagnostics)
999             {
1000                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
1001                                               0);
1002                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1003                                     &res->num_diagnostics, client_data, ns,
1004                                     version2);
1005             }
1006             if (version2)
1007             {
1008                 if (ptr && (*p)->extraResponseData_len)
1009                     add_XML_n(ptr, "extraResponseData",
1010                               (*p)->extraResponseData_buf,
1011                               (*p)->extraResponseData_len, ns_srw);
1012                 add_xsd_integer(ptr, "resultSetTTL", res->resultSetIdleTime);
1013                 add_xsd_string(ptr, "resultCountPrecision",
1014                                res->resultCountPrecision);
1015                 yaz_sru_facet_response(o, &res->facetList, ptr);
1016                 return 0; /* so we don't make extra response data twice */
1017             }
1018         }
1019         else if ((*p)->which == Z_SRW_explain_request)
1020         {
1021             Z_SRW_explainRequest *req = (*p)->u.explain_request;
1022             if (version2)
1023                 ns = "http://docs.oasis-open.org/ns/search-ws/sruRequest";
1024             ptr = xmlNewChild(pptr, 0, BAD_CAST "explainRequest", 0);
1025             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1026             xmlSetNs(ptr, ns_srw);
1027
1028             if (!version2)
1029                 add_xsd_string(ptr, "version", (*p)->srw_version);
1030             if (version2)
1031             {
1032                 add_xsd_string(ptr, "recordXMLEscaping", req->recordPacking);
1033                 add_xsd_string(ptr, "recordPacking", req->packing);
1034             }
1035             else
1036                 add_xsd_string(ptr, "recordPacking", req->recordPacking);
1037             add_xsd_string(ptr, "stylesheet", req->stylesheet);
1038             add_xsd_string(ptr, "database", req->database);
1039         }
1040         else if ((*p)->which == Z_SRW_explain_response)
1041         {
1042             Z_SRW_explainResponse *res = (*p)->u.explain_response;
1043             if (version2)
1044                 ns = "http://docs.oasis-open.org/ns/search-ws/sruResponse";
1045             ptr = xmlNewChild(pptr, 0, BAD_CAST "explainResponse", 0);
1046             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1047             xmlSetNs(ptr, ns_srw);
1048
1049             add_xsd_string(ptr, "version", (*p)->srw_version);
1050             if (1)
1051             {
1052                 xmlNodePtr ptr1 = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
1053                 yaz_srw_record(o, ptr1, &res->record, &res->extra_record,
1054                                client_data, version2);
1055             }
1056             if ((*p)->extra_args)
1057             {
1058                 xmlNode *p1 =
1059                     xmlNewChild(ptr, 0, BAD_CAST "echoedExplainRequest", 0);
1060                 Z_SRW_extra_arg *ea = (*p)->extra_args;
1061                 for (; ea; ea = ea->next)
1062                     add_xsd_string(p1, ea->name, ea->value);
1063             }
1064             if (res->num_diagnostics)
1065             {
1066                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
1067                                               0);
1068                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1069                                     &res->num_diagnostics, client_data, ns,
1070                                     version2);
1071             }
1072         }
1073         else if ((*p)->which == Z_SRW_scan_request)
1074         {
1075             Z_SRW_scanRequest *req = (*p)->u.scan_request;
1076             const char *queryType = req->queryType;
1077             if (version2)
1078                 ns = "http://docs.oasis-open.org/ns/search-ws/scan";
1079             ptr = xmlNewChild(pptr, 0, BAD_CAST "scanRequest", 0);
1080             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1081             xmlSetNs(ptr, ns_srw);
1082
1083             if (!version2)
1084                 add_xsd_string(ptr, "version", (*p)->srw_version);
1085
1086             if (version2)
1087             {
1088                 if (queryType && strcmp(queryType, "cql"))
1089                     add_xsd_string(ptr, "queryType", queryType);
1090                 add_xsd_string(ptr, "scanClause", req->scanClause);
1091             }
1092             else
1093             {
1094                 if (!queryType || !strcmp(queryType, "cql"))
1095                     add_xsd_string(ptr, "scanClause", req->scanClause);
1096                 else if (!strcmp(queryType, "pqf"))
1097                     add_xsd_string(ptr, "pScanClause", req->scanClause);
1098             }
1099             add_xsd_integer(ptr, "responsePosition", req->responsePosition);
1100             add_xsd_integer(ptr, "maximumTerms", req->maximumTerms);
1101             add_xsd_string(ptr, "stylesheet", req->stylesheet);
1102             add_xsd_string(ptr, "database", req->database);
1103         }
1104         else if ((*p)->which == Z_SRW_scan_response)
1105         {
1106             Z_SRW_scanResponse *res = (*p)->u.scan_response;
1107             if (version2)
1108                 ns = "http://docs.oasis-open.org/ns/search-ws/scan";
1109             ptr = xmlNewChild(pptr, 0, BAD_CAST "scanResponse", 0);
1110             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
1111             xmlSetNs(ptr, ns_srw);
1112
1113             if (!version2)
1114                 add_xsd_string(ptr, "version", (*p)->srw_version);
1115             if (res->num_terms)
1116             {
1117                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "terms", 0);
1118                 yaz_srw_terms(o, rptr, &res->terms, &res->num_terms,
1119                               client_data, ns);
1120             }
1121             if (res->num_diagnostics)
1122             {
1123                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
1124                                               0);
1125                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1126                                     &res->num_diagnostics, client_data, ns,
1127                                     version2);
1128             }
1129         }
1130         else
1131             return -1;
1132         if (ptr && (*p)->extraResponseData_len)
1133             add_XML_n(ptr, "extraResponseData",
1134                       (*p)->extraResponseData_buf,
1135                       (*p)->extraResponseData_len, ns_srw);
1136
1137
1138     }
1139     return 0;
1140 }
1141
1142 int yaz_ucp_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
1143                   void *client_data, const char *ns_ucp_str)
1144 {
1145     xmlNodePtr pptr = (xmlNodePtr) vptr;
1146     const char *ns_srw_str = YAZ_XMLNS_SRU_v1_1;
1147     if (o->direction == ODR_DECODE)
1148     {
1149         Z_SRW_PDU **p = handler_data;
1150         xmlNodePtr method = pptr->children;
1151
1152         while (method && method->type == XML_TEXT_NODE)
1153             method = method->next;
1154
1155         if (!method)
1156             return -1;
1157         if (method->type != XML_ELEMENT_NODE)
1158             return -1;
1159
1160         *p = yaz_srw_get_core_v_2_0(o);
1161
1162         if (!xmlStrcmp(method->name, BAD_CAST "updateRequest"))
1163         {
1164             xmlNodePtr ptr = method->children;
1165             Z_SRW_updateRequest *req;
1166             char *oper = 0;
1167
1168             (*p)->which = Z_SRW_update_request;
1169             req = (*p)->u.update_request = (Z_SRW_updateRequest *)
1170                 odr_malloc(o, sizeof(*req));
1171             req->database = 0;
1172             req->operation = 0;
1173             req->recordId = 0;
1174             req->recordVersions = 0;
1175             req->num_recordVersions = 0;
1176             req->record = 0;
1177             req->extra_record = 0;
1178             req->extraRequestData_buf = 0;
1179             req->extraRequestData_len = 0;
1180             req->stylesheet = 0;
1181
1182             for (; ptr; ptr = ptr->next)
1183             {
1184                 if (yaz_match_xsd_string(ptr, "version", o,
1185                                      &(*p)->srw_version))
1186                     ;
1187                 else if (yaz_match_xsd_string(ptr, "action", o,
1188                                           &oper)){
1189                     if (oper)
1190                     {
1191                         if (!strcmp(oper, "info:srw/action/1/delete"))
1192                             req->operation = "delete";
1193                         else if (!strcmp(oper,"info:srw/action/1/replace" ))
1194                             req->operation = "replace";
1195                         else if (!strcmp(oper, "info:srw/action/1/create"))
1196                             req->operation = "insert";
1197                     }
1198                 }
1199                 else if (yaz_match_xsd_string(ptr, "recordIdentifier", o,
1200                                           &req->recordId))
1201                     ;
1202                 else if (yaz_match_xsd_element(ptr, "recordVersions" ) )
1203                     yaz_srw_versions( o, ptr, &req->recordVersions,
1204                                       &req->num_recordVersions, client_data,
1205                                       ns_ucp_str);
1206                 else if (yaz_match_xsd_element(ptr, "record"))
1207                 {
1208                     req->record = yaz_srw_get_record(o);
1209                     yaz_srw_record(o, ptr, req->record, &req->extra_record,
1210                                    client_data, 0);
1211                 }
1212                 else if (yaz_match_xsd_string(ptr, "stylesheet", o,
1213                                           &req->stylesheet))
1214                     ;
1215                 else
1216                     yaz_match_xsd_string(ptr, "database", o, &req->database);
1217             }
1218         }
1219         else if (!xmlStrcmp(method->name, BAD_CAST "updateResponse"))
1220         {
1221             xmlNodePtr ptr = method->children;
1222             Z_SRW_updateResponse *res;
1223
1224             (*p)->which = Z_SRW_update_response;
1225             res = (*p)->u.update_response = (Z_SRW_updateResponse *)
1226                 odr_malloc(o, sizeof(*res));
1227
1228             res->operationStatus = 0;
1229             res->recordId = 0;
1230             res->recordVersions = 0;
1231             res->num_recordVersions = 0;
1232             res->diagnostics = 0;
1233             res->num_diagnostics = 0;
1234             res->record = 0;
1235             res->extra_record = 0;
1236             res->extraResponseData_buf = 0;
1237             res->extraResponseData_len = 0;
1238
1239             for (; ptr; ptr = ptr->next)
1240             {
1241                 if (yaz_match_xsd_string(ptr, "version", o,
1242                                      &(*p)->srw_version))
1243                     ;
1244                 else if (yaz_match_xsd_string(ptr, "operationStatus", o,
1245                                           &res->operationStatus ))
1246                     ;
1247                 else if (yaz_match_xsd_string(ptr, "recordIdentifier", o,
1248                                           &res->recordId))
1249                     ;
1250                 else if (yaz_match_xsd_element(ptr, "recordVersions" ))
1251                     yaz_srw_versions(o, ptr, &res->recordVersions,
1252                                      &res->num_recordVersions,
1253                                      client_data, ns_ucp_str);
1254                 else if (yaz_match_xsd_element(ptr, "record"))
1255                 {
1256                     res->record = yaz_srw_get_record(o);
1257                     yaz_srw_record(o, ptr, res->record, &res->extra_record,
1258                                    client_data, 0);
1259                 }
1260                 else if (yaz_match_xsd_element(ptr, "diagnostics"))
1261                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
1262                                         &res->num_diagnostics,
1263                                         client_data, ns_ucp_str, 0);
1264             }
1265         }
1266         else if (!xmlStrcmp(method->name, BAD_CAST "explainUpdateRequest"))
1267         {
1268         }
1269         else if (!xmlStrcmp(method->name, BAD_CAST "explainUpdateResponse"))
1270         {
1271         }
1272         else
1273         {
1274             *p = 0;
1275             return -1;
1276         }
1277     }
1278     else if (o->direction == ODR_ENCODE)
1279     {
1280         Z_SRW_PDU **p = handler_data;
1281         xmlNsPtr ns_ucp, ns_srw;
1282
1283         if ((*p)->which == Z_SRW_update_request)
1284         {
1285             Z_SRW_updateRequest *req = (*p)->u.update_request;
1286             xmlNodePtr ptr = xmlNewChild(pptr, 0, BAD_CAST "updateRequest", 0);
1287             ns_ucp = xmlNewNs(ptr, BAD_CAST ns_ucp_str, BAD_CAST "zu");
1288             xmlSetNs(ptr, ns_ucp);
1289             ns_srw = xmlNewNs(ptr, BAD_CAST ns_srw_str, BAD_CAST "zs");
1290
1291             add_xsd_string_ns(ptr, "version", (*p)->srw_version, ns_srw);
1292             add_xsd_string(ptr, "action", req->operation);
1293             add_xsd_string(ptr, "recordIdentifier", req->recordId );
1294             if (req->recordVersions)
1295                 yaz_srw_versions( o, ptr, &req->recordVersions,
1296                                   &req->num_recordVersions,
1297                                   client_data, ns_ucp_str);
1298             if (req->record && req->record->recordData_len)
1299             {
1300                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
1301                 xmlSetNs(rptr, ns_srw);
1302                 yaz_srw_record(o, rptr, req->record, &req->extra_record,
1303                                client_data, 0);
1304             }
1305             if (req->extraRequestData_len)
1306             {
1307                 add_XML_n(ptr, "extraRequestData",
1308                           req->extraRequestData_buf,
1309                           req->extraRequestData_len, ns_srw);
1310             }
1311             add_xsd_string(ptr, "stylesheet", req->stylesheet);
1312             add_xsd_string(ptr, "database", req->database);
1313         }
1314         else if ((*p)->which == Z_SRW_update_response)
1315         {
1316             Z_SRW_updateResponse *res = (*p)->u.update_response;
1317             xmlNodePtr ptr = xmlNewChild(pptr, 0, (xmlChar *)
1318                                          "updateResponse", 0);
1319             ns_ucp = xmlNewNs(ptr, BAD_CAST ns_ucp_str, BAD_CAST "zu");
1320             xmlSetNs(ptr, ns_ucp);
1321             ns_srw = xmlNewNs(ptr, BAD_CAST ns_srw_str, BAD_CAST "zs");
1322
1323             add_xsd_string_ns(ptr, "version", (*p)->srw_version, ns_srw);
1324             add_xsd_string(ptr, "operationStatus", res->operationStatus );
1325             add_xsd_string(ptr, "recordIdentifier", res->recordId );
1326             if (res->recordVersions)
1327                 yaz_srw_versions(o, ptr, &res->recordVersions,
1328                                  &res->num_recordVersions,
1329                                  client_data, ns_ucp_str);
1330             if (res->record && res->record->recordData_len)
1331             {
1332                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
1333                 xmlSetNs(rptr, ns_srw);
1334                 yaz_srw_record(o, rptr, res->record, &res->extra_record,
1335                                client_data, 0);
1336             }
1337             if (res->num_diagnostics)
1338             {
1339                 xmlNsPtr ns_diag =
1340                     xmlNewNs(pptr, BAD_CAST YAZ_XMLNS_DIAG_v1_1,
1341                              BAD_CAST "diag" );
1342
1343                 xmlNodePtr rptr = xmlNewChild(ptr, ns_diag, BAD_CAST "diagnostics", 0);
1344                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
1345                                     &res->num_diagnostics, client_data,
1346                                     ns_ucp_str, 0);
1347             }
1348             if (res->extraResponseData_len)
1349                 add_XML_n(ptr, "extraResponseData",
1350                           res->extraResponseData_buf,
1351                           res->extraResponseData_len, ns_srw);
1352         }
1353         else
1354             return -1;
1355     }
1356     return 0;
1357 }
1358
1359 #endif
1360
1361
1362 /*
1363  * Local variables:
1364  * c-basic-offset: 4
1365  * c-file-style: "Stroustrup"
1366  * indent-tabs-mode: nil
1367  * End:
1368  * vim: shiftwidth=4 tabstop=8 expandtab
1369  */
1370