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