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