3c77116b825955c56db4ee6b6862964d9dde1cc1
[yaz-moved-to-github.git] / src / srw.c
1 /*
2  * Copyright (C) 1995-2005, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: srw.c,v 1.36 2005-08-22 20:34:21 adam Exp $
6  */
7 /**
8  * \file srw.c
9  * \brief Implements SRW/SRU package encoding and decoding
10  */
11
12 #include <yaz/srw.h>
13
14 #if HAVE_XML2
15 #include <libxml/parser.h>
16 #include <libxml/tree.h>
17
18 static void add_XML_n(xmlNodePtr ptr, const char *elem, char *val, int len)
19 {
20     if (val)
21     {
22         xmlDocPtr doc = xmlParseMemory(val,len);
23         if (doc)
24         {
25             xmlNodePtr c = xmlNewChild(ptr, 0, BAD_CAST elem, 0);
26             xmlNodePtr t = xmlDocGetRootElement(doc);
27             xmlAddChild(c, xmlCopyNode(t,1));
28             xmlFreeDoc(doc);
29         }
30     }
31 }
32
33 xmlNodePtr add_xsd_string_n(xmlNodePtr ptr, const char *elem, const char *val,
34                             int len)
35 {
36     if (val)
37     {
38         xmlNodePtr c = xmlNewChild(ptr, 0, BAD_CAST elem, 0);
39         xmlNodePtr t = xmlNewTextLen(BAD_CAST val, len);
40         xmlAddChild(c, t);
41         return t;
42     }
43     return 0;
44 }
45
46 xmlNodePtr add_xsd_string(xmlNodePtr ptr, const char *elem, const char *val)
47 {
48     if (val)
49         return xmlNewTextChild(ptr, 0, BAD_CAST elem,
50                                BAD_CAST val);
51     return 0;
52 }
53
54 static void add_xsd_integer(xmlNodePtr ptr, const char *elem, const int *val)
55 {
56     if (val)
57     {
58         char str[30];
59         sprintf(str, "%d", *val);
60         xmlNewTextChild(ptr, 0, BAD_CAST elem, BAD_CAST str);
61     }
62 }
63
64 static int match_element(xmlNodePtr ptr, const char *elem)
65 {
66     if (ptr->type == XML_ELEMENT_NODE && !xmlStrcmp(ptr->name, BAD_CAST elem))
67         return 1;
68     return 0;
69 }
70
71 #define CHECK_TYPE 0
72
73 static int match_xsd_string_n(xmlNodePtr ptr, const char *elem, ODR o,
74                               char **val, int *len)
75 {
76 #if CHECK_TYPE
77     struct _xmlAttr *attr;
78 #endif
79     if (!match_element(ptr, elem))
80         return 0;
81 #if CHECK_TYPE
82     for (attr = ptr->properties; attr; attr = attr->next)
83         if (!strcmp(attr->name, "type") &&
84             attr->children && attr->children->type == XML_TEXT_NODE)
85         {
86             const char *t = strchr(attr->children->content, ':');
87             if (t)
88                 t = t + 1;
89             else
90                 t = attr->children->content;
91             if (!strcmp(t, "string"))
92                 break;
93         }
94     if (!attr)
95         return 0;
96 #endif
97     ptr = ptr->children;
98     if (!ptr || ptr->type != XML_TEXT_NODE)
99     {
100         *val = "";
101         return 1;
102     }
103     *val = odr_strdup(o, (const char *) ptr->content);
104     if (len)
105         *len = xmlStrlen(ptr->content);
106     return 1;
107 }
108
109
110 static int match_xsd_string(xmlNodePtr ptr, const char *elem, ODR o,
111                             char **val)
112 {
113     return match_xsd_string_n(ptr, elem, o, val, 0);
114 }
115
116 static int match_xsd_XML_n(xmlNodePtr ptr, const char *elem, ODR o,
117                            char **val, int *len)
118 {
119     xmlBufferPtr buf;
120
121     if (!match_element(ptr, elem))
122         return 0;
123     ptr = ptr->children;
124     while (ptr && (ptr->type == XML_TEXT_NODE || ptr->type == XML_COMMENT_NODE))
125         ptr = ptr->next;
126     if (!ptr)
127         return 0;
128     buf = xmlBufferCreate();
129     
130     xmlNodeDump(buf, ptr->doc, ptr, 0, 0);
131     
132     *val = odr_malloc(o, buf->use+1);
133     memcpy (*val, buf->content, buf->use);
134     (*val)[buf->use] = '\0';
135
136     if (len)
137         *len = buf->use;
138
139     xmlBufferFree(buf);
140
141     return 1;
142 }
143                      
144 static int match_xsd_integer(xmlNodePtr ptr, const char *elem, ODR o, int **val)
145 {
146 #if CHECK_TYPE
147     struct _xmlAttr *attr;
148 #endif
149     if (!match_element(ptr, elem))
150         return 0;
151 #if CHECK_TYPE
152     for (attr = ptr->properties; attr; attr = attr->next)
153         if (!strcmp(attr->name, "type") &&
154             attr->children && attr->children->type == XML_TEXT_NODE)
155         {
156             const char *t = strchr(attr->children->content, ':');
157             if (t)
158                 t = t + 1;
159             else
160                 t = attr->children->content;
161             if (!strcmp(t, "integer"))
162                 break;
163         }
164     if (!attr)
165         return 0;
166 #endif
167     ptr = ptr->children;
168     if (!ptr || ptr->type != XML_TEXT_NODE)
169         return 0;
170     *val = odr_intdup(o, atoi((const char *) ptr->content));
171     return 1;
172 }
173
174 static int yaz_srw_record(ODR o, xmlNodePtr pptr, Z_SRW_record *rec,
175                           void *client_data, const char *ns)
176 {
177     if (o->direction == ODR_DECODE)
178     {
179         int pack = Z_SRW_recordPacking_string;
180         xmlNodePtr ptr;
181         rec->recordSchema = 0;
182         rec->recordData_buf = 0;
183         rec->recordData_len = 0;
184         rec->recordPosition = 0;
185         for (ptr = pptr->children; ptr; ptr = ptr->next)
186         {
187             char *spack = 0;
188             
189             if (match_xsd_string(ptr, "recordSchema", o, 
190                                  &rec->recordSchema))
191                 ;
192             else if (match_xsd_string(ptr, "recordPacking", o, &spack))
193             {
194                 if (spack && !strcmp(spack, "xml"))
195                     pack = Z_SRW_recordPacking_XML;
196                 if (spack && !strcmp(spack, "string"))
197                     pack = Z_SRW_recordPacking_string;
198             }
199             else if (match_xsd_integer(ptr, "recordPosition", o, 
200                                        &rec->recordPosition))
201                 ;
202             else 
203             {
204                 if (pack == Z_SRW_recordPacking_XML)
205                     match_xsd_XML_n(ptr, "recordData", o, 
206                                     &rec->recordData_buf,
207                                     &rec->recordData_len);
208                 if (pack == Z_SRW_recordPacking_string)
209                     match_xsd_string_n(ptr, "recordData", o, 
210                                        &rec->recordData_buf,
211                                        &rec->recordData_len);
212             }
213         }
214         rec->recordPacking = pack;
215     }
216     else if (o->direction == ODR_ENCODE)
217     {
218         xmlNodePtr ptr = pptr;
219         add_xsd_string(ptr, "recordSchema", rec->recordSchema);
220         switch(rec->recordPacking)
221         {
222         case Z_SRW_recordPacking_string:
223             add_xsd_string(ptr, "recordPacking", "string");
224             add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
225                              rec->recordData_len);
226             break;
227         case Z_SRW_recordPacking_XML:
228             add_xsd_string(ptr, "recordPacking", "xml");
229             add_XML_n(ptr, "recordData", rec->recordData_buf,
230                       rec->recordData_len);
231             break;
232         }
233         add_xsd_integer(ptr, "recordPosition", rec->recordPosition);
234     }
235     return 0;
236 }
237
238 static int yaz_srw_records(ODR o, xmlNodePtr pptr, Z_SRW_record **recs,
239                            int *num, void *client_data, const char *ns)
240 {
241     if (o->direction == ODR_DECODE)
242     {
243         int i;
244         xmlNodePtr ptr;
245         *num = 0;
246         for (ptr = pptr->children; ptr; ptr = ptr->next)
247         {
248             if (ptr->type == XML_ELEMENT_NODE &&
249                 !xmlStrcmp(ptr->name, BAD_CAST "record"))
250                 (*num)++;
251         }
252         if (!*num)
253             return 1;
254         *recs = (Z_SRW_record *) odr_malloc(o, *num * sizeof(**recs));
255         for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next)
256         {
257             if (ptr->type == XML_ELEMENT_NODE &&
258                 !xmlStrcmp(ptr->name, BAD_CAST "record"))
259             {
260                 yaz_srw_record(o, ptr, (*recs)+i, client_data, ns);
261                 i++;
262             }
263         }
264     }
265     else if (o->direction == ODR_ENCODE)
266     {
267         int i;
268         for (i = 0; i < *num; i++)
269         {
270             xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "record",
271                                           0);
272             yaz_srw_record(o, rptr, (*recs)+i, client_data, ns);
273         }
274     }
275     return 0;
276 }
277
278 static int yaz_srw_diagnostics(ODR o, xmlNodePtr pptr, Z_SRW_diagnostic **recs,
279                                int *num, void *client_data, const char *ns)
280 {
281     if (o->direction == ODR_DECODE)
282     {
283         int i;
284         xmlNodePtr ptr;
285         *num = 0;
286         for (ptr = pptr->children; ptr; ptr = ptr->next)
287         {
288             if (ptr->type == XML_ELEMENT_NODE &&
289                 !xmlStrcmp(ptr->name, BAD_CAST "diagnostic"))
290                 (*num)++;
291         }
292         if (!*num)
293             return 1;
294         *recs = (Z_SRW_diagnostic *) odr_malloc(o, *num * sizeof(**recs));
295         for (i = 0; i < *num; i++)
296         {
297             (*recs)[i].uri = 0;
298             (*recs)[i].details = 0;
299             (*recs)[i].message = 0;
300         } 
301         for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next)
302         {
303             if (ptr->type == XML_ELEMENT_NODE &&
304                 !xmlStrcmp(ptr->name, BAD_CAST "diagnostic"))
305             {
306                 xmlNodePtr rptr;
307                 (*recs)[i].uri = 0;
308                 (*recs)[i].details = 0;
309                 (*recs)[i].message = 0;
310                 for (rptr = ptr->children; rptr; rptr = rptr->next)
311                 {
312                     if (match_xsd_string(rptr, "uri", o, 
313                                          &(*recs)[i].uri))
314                         ;
315                     else if (match_xsd_string(rptr, "details", o, 
316                                               &(*recs)[i].details))
317                         ;
318                     else if (match_xsd_string(rptr, "message", o, 
319                                               &(*recs)[i].message))
320                         ;
321                 }
322                 i++;
323             }
324         }
325     }
326     else if (o->direction == ODR_ENCODE)
327     {
328         int i;
329         xmlNsPtr ns_diag =
330             xmlNewNs(pptr, BAD_CAST
331                      "http://www.loc.gov/zing/srw/diagnostic/", 0);
332         for (i = 0; i < *num; i++)
333         {
334             const char *std_diag = "info:srw/diagnostic/1/";
335             xmlNodePtr rptr = xmlNewChild(pptr, ns_diag,
336                                           BAD_CAST "diagnostic", 0);
337             add_xsd_string(rptr, "uri", (*recs)[i].uri);
338             if ((*recs)[i].message)
339                 add_xsd_string(rptr, "message", (*recs)[i].message);
340             else if ((*recs)[i].uri && 
341                      !strncmp((*recs)[i].uri, std_diag, strlen(std_diag)))
342             {
343                 int no = atoi((*recs)[i].uri + strlen(std_diag));
344                 const char *message = yaz_diag_srw_str(no);
345                 if (message)
346                     add_xsd_string(rptr, "message", message);
347             }
348             add_xsd_string(rptr, "details", (*recs)[i].details);
349         }
350     }
351     return 0;
352 }
353
354 static int yaz_srw_term(ODR o, xmlNodePtr pptr, Z_SRW_scanTerm *term,
355                         void *client_data, const char *ns)
356 {
357     if (o->direction == ODR_DECODE)
358     {
359         xmlNodePtr ptr;
360         term->value = 0;
361         term->numberOfRecords = 0;
362         term->displayTerm = 0;
363         term->whereInList = 0;
364         for (ptr = pptr->children; ptr; ptr = ptr->next)
365         {
366             if (match_xsd_string(ptr, "value", o,  &term->value))
367                 ;
368             else if (match_xsd_integer(ptr, "numberOfRecords", o, 
369                                    &term->numberOfRecords))
370                 ;
371             else if (match_xsd_string(ptr, "displayTerm", o, 
372                                       &term->displayTerm))
373                 ;
374             else if (match_xsd_string(ptr, "whereInList", o, 
375                                       &term->whereInList))
376                 ;
377         }
378     }
379     else if (o->direction == ODR_ENCODE)
380     {
381         xmlNodePtr ptr = pptr;
382         add_xsd_string(ptr, "value", term->value);
383         add_xsd_integer(ptr, "numberOfRecords", term->numberOfRecords);
384         add_xsd_string(ptr, "displayTerm", term->displayTerm);
385         add_xsd_string(ptr, "whereInList", term->whereInList);
386     }
387     return 0;
388 }
389
390 static int yaz_srw_terms(ODR o, xmlNodePtr pptr, Z_SRW_scanTerm **terms,
391                          int *num, void *client_data, const char *ns)
392 {
393     if (o->direction == ODR_DECODE)
394     {
395         int i;
396         xmlNodePtr ptr;
397         *num = 0;
398         for (ptr = pptr->children; ptr; ptr = ptr->next)
399         {
400             if (ptr->type == XML_ELEMENT_NODE &&
401                 !xmlStrcmp(ptr->name, BAD_CAST "term"))
402                 (*num)++;
403         }
404         if (!*num)
405             return 1;
406         *terms = (Z_SRW_scanTerm *) odr_malloc(o, *num * sizeof(**terms));
407         for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next, i++)
408         {
409             if (ptr->type == XML_ELEMENT_NODE &&
410                 !xmlStrcmp(ptr->name, BAD_CAST "term"))
411                 yaz_srw_term(o, ptr, (*terms)+i, client_data, ns);
412         }
413     }
414     else if (o->direction == ODR_ENCODE)
415     {
416         int i;
417         for (i = 0; i < *num; i++)
418         {
419             xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "term", 0);
420             yaz_srw_term(o, rptr, (*terms)+i, client_data, ns);
421         }
422     }
423     return 0;
424 }
425
426 int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
427                   void *client_data, const char *ns)
428 {
429     xmlNodePtr pptr = (xmlNodePtr) vptr;
430     if (o->direction == ODR_DECODE)
431     {
432         Z_SRW_PDU **p = handler_data;
433         xmlNodePtr method = pptr->children;
434
435         while (method && method->type == XML_TEXT_NODE)
436             method = method->next;
437         
438         if (!method)
439             return -1;
440         if (method->type != XML_ELEMENT_NODE)
441             return -1;
442
443         *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(**p));
444         (*p)->srw_version = odr_strdup(o, "1.1");
445         
446         if (!xmlStrcmp(method->name, BAD_CAST "searchRetrieveRequest"))
447         {
448             xmlNodePtr ptr = method->children;
449             Z_SRW_searchRetrieveRequest *req;
450
451             (*p)->which = Z_SRW_searchRetrieve_request;
452             req = (*p)->u.request = (Z_SRW_searchRetrieveRequest *)
453                 odr_malloc(o, sizeof(*req));
454             req->query_type = Z_SRW_query_type_cql;
455             req->query.cql = 0;
456             req->sort_type = Z_SRW_sort_type_none;
457             req->sort.none = 0;
458             req->startRecord = 0;
459             req->maximumRecords = 0;
460             req->recordSchema = 0;
461             req->recordPacking = 0;
462             req->recordXPath = 0;
463             req->resultSetTTL = 0;
464             req->stylesheet = 0;
465             req->database = 0;
466
467             for (; ptr; ptr = ptr->next)
468             {
469                 if (match_xsd_string(ptr, "version", o,
470                                      &(*p)->srw_version))
471                     ;
472                 else if (match_xsd_string(ptr, "query", o, 
473                                      &req->query.cql))
474                     req->query_type = Z_SRW_query_type_cql;
475                 else if (match_xsd_string(ptr, "pQuery", o, 
476                                      &req->query.pqf))
477                     req->query_type = Z_SRW_query_type_pqf;
478                 else if (match_xsd_string(ptr, "xQuery", o, 
479                                      &req->query.xcql))
480                     req->query_type = Z_SRW_query_type_xcql;
481                 else if (match_xsd_integer(ptr, "startRecord", o,
482                                            &req->startRecord))
483                     ;
484                 else if (match_xsd_integer(ptr, "maximumRecords", o,
485                                            &req->maximumRecords))
486                     ;
487                 else if (match_xsd_string(ptr, "recordPacking", o,
488                                           &req->recordPacking))
489                     ;
490                 else if (match_xsd_string(ptr, "recordSchema", o, 
491                                           &req->recordSchema))
492                     ;
493                 else if (match_xsd_string(ptr, "recordXPath", o,
494                                           &req->recordXPath))
495                     ;
496                 else if (match_xsd_string(ptr, "resultSetTTL", o,
497                                            &req->database))
498                     ;
499                 else if (match_xsd_string(ptr, "sortKeys", o, 
500                                           &req->sort.sortKeys))
501                     req->sort_type = Z_SRW_sort_type_sort;
502                 else if (match_xsd_string(ptr, "stylesheet", o,
503                                            &req->stylesheet))
504                     ;
505                 else if (match_xsd_string(ptr, "database", o,
506                                            &req->database))
507                     ;
508                 /* missing is xQuery, xSortKeys .. */
509             }
510         }
511         else if (!xmlStrcmp(method->name, BAD_CAST "searchRetrieveResponse"))
512         {
513             xmlNodePtr ptr = method->children;
514             Z_SRW_searchRetrieveResponse *res;
515
516             (*p)->which = Z_SRW_searchRetrieve_response;
517             res = (*p)->u.response = (Z_SRW_searchRetrieveResponse *)
518                 odr_malloc(o, sizeof(*res));
519
520             res->numberOfRecords = 0;
521             res->resultSetId = 0;
522             res->resultSetIdleTime = 0;
523             res->records = 0;
524             res->num_records = 0;
525             res->diagnostics = 0;
526             res->num_diagnostics = 0;
527             res->nextRecordPosition = 0;
528
529             for (; ptr; ptr = ptr->next)
530             {
531                 if (match_xsd_string(ptr, "version", o,
532                                      &(*p)->srw_version))
533                     ;
534                 else if (match_xsd_integer(ptr, "numberOfRecords", o, 
535                                       &res->numberOfRecords))
536                     ;
537                 else if (match_xsd_string(ptr, "resultSetId", o, 
538                                           &res->resultSetId))
539                     ;
540                 else if (match_xsd_integer(ptr, "resultSetIdleTime", o, 
541                                            &res->resultSetIdleTime))
542                     ;
543                 else if (match_element(ptr, "records"))
544                     yaz_srw_records(o, ptr, &res->records,
545                                     &res->num_records, client_data,
546                                     ns);
547                 else if (match_xsd_integer(ptr, "nextRecordPosition", o,
548                                            &res->nextRecordPosition))
549                     ;
550                 else if (match_element(ptr, "diagnostics"))
551                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
552                                         &res->num_diagnostics,
553                                         client_data, ns);
554             }
555         }
556         else if (!xmlStrcmp(method->name, BAD_CAST "explainRequest"))
557         {
558             Z_SRW_explainRequest *req;
559             xmlNodePtr ptr = method->children;
560             
561             (*p)->which = Z_SRW_explain_request;
562             req = (*p)->u.explain_request = (Z_SRW_explainRequest *)
563                 odr_malloc(o, sizeof(*req));
564             req->recordPacking = 0;
565             req->database = 0;
566             req->stylesheet = 0;
567             for (; ptr; ptr = ptr->next)
568             {
569                 if (match_xsd_string(ptr, "version", o,
570                                            &(*p)->srw_version))
571                     ;
572                 else if (match_xsd_string(ptr, "stylesheet", o,
573                                           &req->stylesheet))
574                     ;
575                 else if (match_xsd_string(ptr, "recordPacking", o,
576                                      &req->recordPacking))
577                     ;
578                 else if (match_xsd_string(ptr, "database", o,
579                                      &req->database))
580                     ;
581             }
582         }
583         else if (!xmlStrcmp(method->name, BAD_CAST "explainResponse"))
584         {
585             Z_SRW_explainResponse *res;
586             xmlNodePtr ptr = method->children;
587
588             (*p)->which = Z_SRW_explain_response;
589             res = (*p)->u.explain_response = (Z_SRW_explainResponse*)
590                 odr_malloc(o, sizeof(*res));
591             res->diagnostics = 0;
592             res->num_diagnostics = 0;
593             res->record.recordSchema = 0;
594             res->record.recordData_buf = 0;
595             res->record.recordData_len = 0;
596             res->record.recordPosition = 0;
597
598             for (; ptr; ptr = ptr->next)
599             {
600                 if (match_xsd_string(ptr, "version", o,
601                                            &(*p)->srw_version))
602                     ;
603                 else if (match_element(ptr, "record"))
604                     yaz_srw_record(o, ptr, &res->record, client_data, ns);
605                 else if (match_element(ptr, "diagnostics"))
606                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
607                                         &res->num_diagnostics,
608                                         client_data, ns);
609                 ;
610             }
611         }
612         else if (!xmlStrcmp(method->name, BAD_CAST "scanRequest"))
613         {
614             Z_SRW_scanRequest *req;
615             xmlNodePtr ptr = method->children;
616
617             (*p)->which = Z_SRW_scan_request;
618             req = (*p)->u.scan_request = (Z_SRW_scanRequest *)
619                 odr_malloc(o, sizeof(*req));
620             req->query_type = Z_SRW_query_type_cql;
621             req->scanClause.cql = 0;
622             req->responsePosition = 0;
623             req->maximumTerms = 0;
624             req->stylesheet = 0;
625             req->database = 0;
626             
627             for (; ptr; ptr = ptr->next)
628             {
629                 if (match_xsd_string(ptr, "version", o,
630                                      &(*p)->srw_version))
631                     ;
632                 else if (match_xsd_string(ptr, "scanClause", o,
633                                      &req->scanClause.cql))
634                     ;
635                 else if (match_xsd_string(ptr, "pScanClause", o,
636                                           &req->scanClause.pqf))
637                 {
638                     req->query_type = Z_SRW_query_type_pqf;
639                 }
640                 else if (match_xsd_integer(ptr, "responsePosition", o,
641                                            &req->responsePosition))
642                     ;
643                 else if (match_xsd_integer(ptr, "maximumTerms", o,
644                                            &req->maximumTerms))
645                     ;
646                 else if (match_xsd_string(ptr, "stylesheet", o,
647                                           &req->stylesheet))
648                     ;
649                 else if (match_xsd_string(ptr, "database", o,
650                                           &req->database))
651                     ;
652             }
653         }
654         else if (!xmlStrcmp(method->name, BAD_CAST "scanResponse"))
655         {
656             Z_SRW_scanResponse *res;
657             xmlNodePtr ptr = method->children;
658
659             (*p)->which = Z_SRW_scan_response;
660             res = (*p)->u.scan_response = (Z_SRW_scanResponse *)
661                 odr_malloc(o, sizeof(*res));
662             res->terms = 0;
663             res->num_terms = 0;
664             res->diagnostics = 0;
665             res->num_diagnostics = 0;
666             
667             for (; ptr; ptr = ptr->next)
668             {
669                 if (match_xsd_string(ptr, "version", o,
670                                      &(*p)->srw_version))
671                     ;
672                 else if (match_element(ptr, "terms"))
673                     yaz_srw_terms(o, ptr, &res->terms,
674                                   &res->num_terms, client_data,
675                                   ns);
676                 else if (match_element(ptr, "diagnostics"))
677                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
678                                         &res->num_diagnostics,
679                                         client_data, ns);
680             }
681         }
682         else
683         {
684             *p = 0;
685             return -1;
686         }
687     }
688     else if (o->direction == ODR_ENCODE)
689     {
690         Z_SRW_PDU **p = handler_data;
691         xmlNsPtr ns_srw;
692         
693         if ((*p)->which == Z_SRW_searchRetrieve_request)
694         {
695             Z_SRW_searchRetrieveRequest *req = (*p)->u.request;
696             xmlNodePtr ptr = xmlNewChild(pptr, 0,
697                                          BAD_CAST "searchRetrieveRequest", 0);
698             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
699             xmlSetNs(ptr, ns_srw);
700
701             if ((*p)->srw_version)
702                 add_xsd_string(ptr, "version", (*p)->srw_version);
703             switch(req->query_type)
704             {
705             case Z_SRW_query_type_cql:
706                 add_xsd_string(ptr, "query", req->query.cql);
707                 break;
708             case Z_SRW_query_type_xcql:
709                 add_xsd_string(ptr, "xQuery", req->query.xcql);
710                 break;
711             case Z_SRW_query_type_pqf:
712                 add_xsd_string(ptr, "pQuery", req->query.pqf);
713                 break;
714             }
715             add_xsd_integer(ptr, "startRecord", req->startRecord);
716             add_xsd_integer(ptr, "maximumRecords", req->maximumRecords);
717             add_xsd_string(ptr, "recordPacking", req->recordPacking);
718             add_xsd_string(ptr, "recordSchema", req->recordSchema);
719             add_xsd_string(ptr, "recordXPath", req->recordXPath);
720             add_xsd_integer(ptr, "resultSetTTL", req->resultSetTTL);
721             switch(req->sort_type)
722             {
723             case Z_SRW_sort_type_none:
724                 break;
725             case Z_SRW_sort_type_sort:
726                 add_xsd_string(ptr, "sortKeys", req->sort.sortKeys);
727                 break;
728             case Z_SRW_sort_type_xSort:
729                 add_xsd_string(ptr, "xSortKeys", req->sort.xSortKeys);
730                 break;
731             }
732             add_xsd_string(ptr, "stylesheet", req->stylesheet);
733             add_xsd_string(ptr, "database", req->database);
734         }
735         else if ((*p)->which == Z_SRW_searchRetrieve_response)
736         {
737             Z_SRW_searchRetrieveResponse *res = (*p)->u.response;
738             xmlNodePtr ptr = xmlNewChild(pptr, 0,
739                                          BAD_CAST "searchRetrieveResponse", 0);
740             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
741             xmlSetNs(ptr, ns_srw);
742
743             if ((*p)->srw_version)
744                 add_xsd_string(ptr, "version", (*p)->srw_version);
745             add_xsd_integer(ptr, "numberOfRecords", res->numberOfRecords);
746             add_xsd_string(ptr, "resultSetId", res->resultSetId);
747             add_xsd_integer(ptr, "resultSetIdleTime", res->resultSetIdleTime);
748             if (res->num_records)
749             {
750                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "records", 0);
751                 yaz_srw_records(o, rptr, &res->records, &res->num_records,
752                                 client_data, ns);
753             }
754             add_xsd_integer(ptr, "nextRecordPosition",
755                             res->nextRecordPosition);
756             if (res->num_diagnostics)
757             {
758                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
759                                               0);
760                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
761                                     &res->num_diagnostics, client_data, ns);
762             }
763         }
764         else if ((*p)->which == Z_SRW_explain_request)
765         {
766             Z_SRW_explainRequest *req = (*p)->u.explain_request;
767             xmlNodePtr ptr = xmlNewChild(pptr, 0, BAD_CAST "explainRequest",
768                                          0);
769             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
770             xmlSetNs(ptr, ns_srw);
771
772             add_xsd_string(ptr, "version", (*p)->srw_version);
773             add_xsd_string(ptr, "recordPacking", req->recordPacking);
774             add_xsd_string(ptr, "stylesheet", req->stylesheet);
775             add_xsd_string(ptr, "database", req->database);
776         }
777         else if ((*p)->which == Z_SRW_explain_response)
778         {
779             Z_SRW_explainResponse *res = (*p)->u.explain_response;
780             xmlNodePtr ptr = xmlNewChild(pptr, 0, BAD_CAST "explainResponse",
781                                          0);
782             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
783             xmlSetNs(ptr, ns_srw);
784
785             add_xsd_string(ptr, "version", (*p)->srw_version);
786             if (1)
787             {
788                 xmlNodePtr ptr1 = xmlNewChild(ptr, 0, BAD_CAST "record", 0);
789                 yaz_srw_record(o, ptr1, &res->record, client_data, ns);
790             }
791             if (res->num_diagnostics)
792             {
793                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
794                                               0);
795                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
796                                     &res->num_diagnostics, client_data, ns);
797             }
798         }
799         else if ((*p)->which == Z_SRW_scan_request)
800         {
801             Z_SRW_scanRequest *req = (*p)->u.scan_request;
802             xmlNodePtr ptr = xmlNewChild(pptr, 0, BAD_CAST "scanRequest", 0);
803             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
804             xmlSetNs(ptr, ns_srw);
805
806             add_xsd_string(ptr, "version", (*p)->srw_version);
807             switch(req->query_type)
808             {
809             case Z_SRW_query_type_cql:
810                 add_xsd_string(ptr, "scanClause", req->scanClause.cql);
811                 break;
812             case Z_SRW_query_type_pqf:
813                 add_xsd_string(ptr, "pScanClause", req->scanClause.pqf);
814                 break;
815             }
816             add_xsd_integer(ptr, "responsePosition", req->responsePosition);
817             add_xsd_integer(ptr, "maximumTerms", req->maximumTerms);
818             add_xsd_string(ptr, "stylesheet", req->stylesheet);
819             add_xsd_string(ptr, "database", req->database);
820         }
821         else if ((*p)->which == Z_SRW_scan_response)
822         {
823             Z_SRW_scanResponse *res = (*p)->u.scan_response;
824             xmlNodePtr ptr = xmlNewChild(pptr, 0, BAD_CAST "scanResponse", 0);
825             ns_srw = xmlNewNs(ptr, BAD_CAST ns, BAD_CAST "zs");
826             xmlSetNs(ptr, ns_srw);
827
828             add_xsd_string(ptr, "version", (*p)->srw_version);
829
830             if (res->num_terms)
831             {
832                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "terms", 0);
833                 yaz_srw_terms(o, rptr, &res->terms, &res->num_terms,
834                               client_data, ns);
835             }
836             if (res->num_diagnostics)
837             {
838                 xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "diagnostics",
839                                               0);
840                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
841                                     &res->num_diagnostics, client_data, ns);
842             }
843         }
844         else
845             return -1;
846
847     }
848     return 0;
849 }
850
851 #endif
852
853
854 /*
855  * Local variables:
856  * c-basic-offset: 4
857  * indent-tabs-mode: nil
858  * End:
859  * vim: shiftwidth=4 tabstop=8 expandtab
860  */
861