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