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