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