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