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