Bug fix: explainRequest decoder did not initialize some members when
[yaz-moved-to-github.git] / src / srw.c
1 /*
2  * Copyright (c) 2002-2004, Index Data.
3  * See the file LICENSE for details.
4  *
5  * $Id: srw.c,v 1.28 2004-10-31 19:23:22 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         for (ptr = pptr->children; ptr; ptr = ptr->next)
357         {
358             if (match_xsd_string(ptr, "value", o,  &term->value))
359                 ;
360             else if (match_xsd_integer(ptr, "numberOfRecords", o, 
361                                    &term->numberOfRecords))
362                 ;
363             else if (match_xsd_string(ptr, "displayTerm", o, 
364                                       &term->displayTerm))
365                 ;
366         }
367     }
368     else if (o->direction == ODR_ENCODE)
369     {
370         xmlNodePtr ptr = pptr;
371         add_xsd_string(ptr, "value", term->value);
372         add_xsd_integer(ptr, "value", term->numberOfRecords);
373         add_xsd_string(ptr, "displayTerm", term->displayTerm);
374     }
375     return 0;
376 }
377
378 static int yaz_srw_terms(ODR o, xmlNodePtr pptr, Z_SRW_scanTerm **terms,
379                          int *num, void *client_data, const char *ns)
380 {
381     if (o->direction == ODR_DECODE)
382     {
383         int i;
384         xmlNodePtr ptr;
385         *num = 0;
386         for (ptr = pptr->children; ptr; ptr = ptr->next)
387         {
388             if (ptr->type == XML_ELEMENT_NODE &&
389                 !strcmp(ptr->name, "term"))
390                 (*num)++;
391         }
392         if (!*num)
393             return 1;
394         *terms = (Z_SRW_scanTerm *) odr_malloc(o, *num * sizeof(**terms));
395         for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next, i++)
396         {
397             if (ptr->type == XML_ELEMENT_NODE &&
398                 !strcmp(ptr->name, "term"))
399                 yaz_srw_term(o, ptr, (*terms)+i, client_data, ns);
400         }
401     }
402     else if (o->direction == ODR_ENCODE)
403     {
404         int i;
405         for (i = 0; i < *num; i++)
406         {
407             xmlNodePtr rptr = xmlNewChild(pptr, 0, "term", 0);
408             yaz_srw_term(o, rptr, (*terms)+i, client_data, ns);
409         }
410     }
411     return 0;
412 }
413
414 int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
415                   void *client_data, const char *ns)
416 {
417     xmlNodePtr pptr = (xmlNodePtr) vptr;
418     if (o->direction == ODR_DECODE)
419     {
420         Z_SRW_PDU **p = handler_data;
421         xmlNodePtr method = pptr->children;
422
423         while (method && method->type == XML_TEXT_NODE)
424             method = method->next;
425         
426         if (!method)
427             return -1;
428         if (method->type != XML_ELEMENT_NODE)
429             return -1;
430
431         *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(**p));
432         (*p)->srw_version = odr_strdup(o, "1.1");
433         
434         if (!strcmp(method->name, "searchRetrieveRequest"))
435         {
436             xmlNodePtr ptr = method->children;
437             Z_SRW_searchRetrieveRequest *req;
438
439             (*p)->which = Z_SRW_searchRetrieve_request;
440             req = (*p)->u.request = (Z_SRW_searchRetrieveRequest *)
441                 odr_malloc(o, sizeof(*req));
442             req->query_type = Z_SRW_query_type_cql;
443             req->query.cql = 0;
444             req->sort_type = Z_SRW_sort_type_none;
445             req->sort.none = 0;
446             req->startRecord = 0;
447             req->maximumRecords = 0;
448             req->recordSchema = 0;
449             req->recordPacking = 0;
450             req->recordXPath = 0;
451             req->resultSetTTL = 0;
452             req->stylesheet = 0;
453             req->database = 0;
454
455             for (; ptr; ptr = ptr->next)
456             {
457                 if (match_xsd_string(ptr, "version", o,
458                                      &(*p)->srw_version))
459                     ;
460                 else if (match_xsd_string(ptr, "query", o, 
461                                      &req->query.cql))
462                     req->query_type = Z_SRW_query_type_cql;
463                 else if (match_xsd_string(ptr, "pQuery", o, 
464                                      &req->query.pqf))
465                     req->query_type = Z_SRW_query_type_pqf;
466                 else if (match_xsd_string(ptr, "xQuery", o, 
467                                      &req->query.xcql))
468                     req->query_type = Z_SRW_query_type_xcql;
469                 else if (match_xsd_integer(ptr, "startRecord", o,
470                                            &req->startRecord))
471                     ;
472                 else if (match_xsd_integer(ptr, "maximumRecords", o,
473                                            &req->maximumRecords))
474                     ;
475                 else if (match_xsd_string(ptr, "recordPacking", o,
476                                           &req->recordPacking))
477                     ;
478                 else if (match_xsd_string(ptr, "recordSchema", o, 
479                                           &req->recordSchema))
480                     ;
481                 else if (match_xsd_string(ptr, "recordXPath", o,
482                                           &req->recordXPath))
483                     ;
484                 else if (match_xsd_string(ptr, "resultSetTTL", o,
485                                            &req->database))
486                     ;
487                 else if (match_xsd_string(ptr, "sortKeys", o, 
488                                           &req->sort.sortKeys))
489                     req->sort_type = Z_SRW_sort_type_sort;
490                 else if (match_xsd_string(ptr, "stylesheet", o,
491                                            &req->stylesheet))
492                     ;
493                 else if (match_xsd_string(ptr, "database", o,
494                                            &req->database))
495                     ;
496                 /* missing is xQuery, xSortKeys .. */
497             }
498         }
499         else if (!strcmp(method->name, "searchRetrieveResponse"))
500         {
501             xmlNodePtr ptr = method->children;
502             Z_SRW_searchRetrieveResponse *res;
503
504             (*p)->which = Z_SRW_searchRetrieve_response;
505             res = (*p)->u.response = (Z_SRW_searchRetrieveResponse *)
506                 odr_malloc(o, sizeof(*res));
507
508             res->numberOfRecords = 0;
509             res->resultSetId = 0;
510             res->resultSetIdleTime = 0;
511             res->records = 0;
512             res->num_records = 0;
513             res->diagnostics = 0;
514             res->num_diagnostics = 0;
515             res->nextRecordPosition = 0;
516
517             for (; ptr; ptr = ptr->next)
518             {
519                 if (match_xsd_string(ptr, "version", o,
520                                      &(*p)->srw_version))
521                     ;
522                 else if (match_xsd_integer(ptr, "numberOfRecords", o, 
523                                       &res->numberOfRecords))
524                     ;
525                 else if (match_xsd_string(ptr, "resultSetId", o, 
526                                           &res->resultSetId))
527                     ;
528                 else if (match_xsd_integer(ptr, "resultSetIdleTime", o, 
529                                            &res->resultSetIdleTime))
530                     ;
531                 else if (match_element(ptr, "records"))
532                     yaz_srw_records(o, ptr, &res->records,
533                                     &res->num_records, client_data,
534                                     ns);
535                 else if (match_xsd_integer(ptr, "nextRecordPosition", o,
536                                            &res->nextRecordPosition))
537                     ;
538                 else if (match_element(ptr, "diagnostics"))
539                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
540                                         &res->num_diagnostics,
541                                         client_data, ns);
542             }
543         }
544         else if (!strcmp(method->name, "explainRequest"))
545         {
546             Z_SRW_explainRequest *req;
547             xmlNodePtr ptr = method->children;
548             
549             (*p)->which = Z_SRW_explain_request;
550             req = (*p)->u.explain_request = (Z_SRW_explainRequest *)
551                 odr_malloc(o, sizeof(*req));
552             req->recordPacking = 0;
553             req->database = 0;
554             req->stylesheet = 0;
555             for (; ptr; ptr = ptr->next)
556             {
557                 if (match_xsd_string(ptr, "version", o,
558                                            &(*p)->srw_version))
559                     ;
560                 else if (match_xsd_string(ptr, "stylesheet", o,
561                                           &req->stylesheet))
562                     ;
563                 else if (match_xsd_string(ptr, "recordPacking", o,
564                                      &req->recordPacking))
565                     ;
566                 else if (match_xsd_string(ptr, "database", o,
567                                      &req->database))
568                     ;
569             }
570         }
571         else if (!strcmp(method->name, "explainResponse"))
572         {
573             Z_SRW_explainResponse *res;
574             xmlNodePtr ptr = method->children;
575
576             (*p)->which = Z_SRW_explain_response;
577             res = (*p)->u.explain_response = (Z_SRW_explainResponse*)
578                 odr_malloc(o, sizeof(*res));
579             res->diagnostics = 0;
580             res->num_diagnostics = 0;
581             res->record.recordSchema = 0;
582             res->record.recordData_buf = 0;
583             res->record.recordData_len = 0;
584             res->record.recordPosition = 0;
585
586             for (; ptr; ptr = ptr->next)
587             {
588                 if (match_xsd_string(ptr, "version", o,
589                                            &(*p)->srw_version))
590                     ;
591                 else if (match_element(ptr, "record"))
592                     yaz_srw_record(o, ptr, &res->record, client_data, ns);
593                 else if (match_element(ptr, "diagnostics"))
594                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
595                                         &res->num_diagnostics,
596                                         client_data, ns);
597                 ;
598             }
599         }
600         else if (!strcmp(method->name, "scanRequest"))
601         {
602             Z_SRW_scanRequest *req;
603             xmlNodePtr ptr = method->children;
604
605             (*p)->which = Z_SRW_scan_request;
606             req = (*p)->u.scan_request = (Z_SRW_scanRequest *)
607                 odr_malloc(o, sizeof(*req));
608             req->database = 0;
609             req->scanClause = 0;
610             req->stylesheet = 0;
611             req->responsePosition = 0;
612             req->maximumTerms = 0;
613             
614             for (; ptr; ptr = ptr->next)
615             {
616                 if (match_xsd_string(ptr, "version", o,
617                                      &(*p)->srw_version))
618                     ;
619                 else if (match_xsd_string(ptr, "scanClause", o,
620                                      &req->scanClause))
621                     ;
622                 else if (match_xsd_integer(ptr, "responsePosition", o,
623                                            &req->responsePosition))
624                     ;
625                 else if (match_xsd_integer(ptr, "maximumTerms", o,
626                                            &req->maximumTerms))
627                     ;
628                 else if (match_xsd_string(ptr, "stylesheet", o,
629                                           &req->stylesheet))
630                     ;
631                 else if (match_xsd_string(ptr, "database", o,
632                                           &req->database))
633                     ;
634             }
635         }
636         else if (!strcmp(method->name, "scanResponse"))
637         {
638             Z_SRW_scanResponse *res;
639             xmlNodePtr ptr = method->children;
640
641             (*p)->which = Z_SRW_scan_response;
642             res = (*p)->u.scan_response = (Z_SRW_scanResponse *)
643                 odr_malloc(o, sizeof(*res));
644             res->terms = 0;
645             res->num_terms = 0;
646             res->diagnostics = 0;
647             res->num_diagnostics = 0;
648             
649             for (; ptr; ptr = ptr->next)
650             {
651                 if (match_xsd_string(ptr, "version", o,
652                                      &(*p)->srw_version))
653                     ;
654                 else if (match_element(ptr, "terms"))
655                     yaz_srw_terms(o, ptr, &res->terms,
656                                   &res->num_terms, client_data,
657                                   ns);
658                 else if (match_element(ptr, "diagnostics"))
659                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
660                                         &res->num_diagnostics,
661                                         client_data, ns);
662             }
663         }
664         else
665         {
666             *p = 0;
667             return -1;
668         }
669     }
670     else if (o->direction == ODR_ENCODE)
671     {
672         Z_SRW_PDU **p = handler_data;
673         xmlNsPtr ns_srw;
674         
675         if ((*p)->which == Z_SRW_searchRetrieve_request)
676         {
677             Z_SRW_searchRetrieveRequest *req = (*p)->u.request;
678             xmlNodePtr ptr = xmlNewChild(pptr, 0,
679                                          "searchRetrieveRequest", 0);
680             ns_srw = xmlNewNs(ptr, ns, "zs");
681             xmlSetNs(ptr, ns_srw);
682
683             if ((*p)->srw_version)
684                 add_xsd_string(ptr, "version", (*p)->srw_version);
685             switch(req->query_type)
686             {
687             case Z_SRW_query_type_cql:
688                 add_xsd_string(ptr, "query", req->query.cql);
689                 break;
690             case Z_SRW_query_type_xcql:
691                 add_xsd_string(ptr, "xQuery", req->query.xcql);
692                 break;
693             case Z_SRW_query_type_pqf:
694                 add_xsd_string(ptr, "pQuery", req->query.pqf);
695                 break;
696             }
697             add_xsd_integer(ptr, "startRecord", req->startRecord);
698             add_xsd_integer(ptr, "maximumRecords", req->maximumRecords);
699             add_xsd_string(ptr, "recordPacking", req->recordPacking);
700             add_xsd_string(ptr, "recordSchema", req->recordSchema);
701             add_xsd_string(ptr, "recordXPath", req->recordXPath);
702             add_xsd_integer(ptr, "resultSetTTL", req->resultSetTTL);
703             switch(req->sort_type)
704             {
705             case Z_SRW_sort_type_none:
706                 break;
707             case Z_SRW_sort_type_sort:
708                 add_xsd_string(ptr, "sortKeys", req->sort.sortKeys);
709                 break;
710             case Z_SRW_sort_type_xSort:
711                 add_xsd_string(ptr, "xSortKeys", req->sort.xSortKeys);
712                 break;
713             }
714             add_xsd_string(ptr, "stylesheet", req->stylesheet);
715             add_xsd_string(ptr, "database", req->database);
716         }
717         else if ((*p)->which == Z_SRW_searchRetrieve_response)
718         {
719             Z_SRW_searchRetrieveResponse *res = (*p)->u.response;
720             xmlNodePtr ptr = xmlNewChild(pptr, 0,
721                                          "searchRetrieveResponse", 0);
722             ns_srw = xmlNewNs(ptr, ns, "zs");
723             xmlSetNs(ptr, ns_srw);
724
725             if ((*p)->srw_version)
726                 add_xsd_string(ptr, "version", (*p)->srw_version);
727             add_xsd_integer(ptr, "numberOfRecords", res->numberOfRecords);
728             add_xsd_string(ptr, "resultSetId", res->resultSetId);
729             add_xsd_integer(ptr, "resultSetIdleTime", res->resultSetIdleTime);
730             if (res->num_records)
731             {
732                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "records", 0);
733                 yaz_srw_records(o, rptr, &res->records, &res->num_records,
734                                 client_data, ns);
735             }
736             add_xsd_integer(ptr, "nextRecordPosition",
737                             res->nextRecordPosition);
738             if (res->num_diagnostics)
739             {
740                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "diagnostics", 0);
741                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
742                                     &res->num_diagnostics, client_data, ns);
743             }
744         }
745         else if ((*p)->which == Z_SRW_explain_request)
746         {
747             Z_SRW_explainRequest *req = (*p)->u.explain_request;
748             xmlNodePtr ptr = xmlNewChild(pptr, 0, "explainRequest", 0);
749             ns_srw = xmlNewNs(ptr, ns, "zs");
750             xmlSetNs(ptr, ns_srw);
751
752             add_xsd_string(ptr, "version", (*p)->srw_version);
753             add_xsd_string(ptr, "recordPacking", req->recordPacking);
754             add_xsd_string(ptr, "stylesheet", req->stylesheet);
755             add_xsd_string(ptr, "database", req->database);
756         }
757         else if ((*p)->which == Z_SRW_explain_response)
758         {
759             Z_SRW_explainResponse *res = (*p)->u.explain_response;
760             xmlNodePtr ptr = xmlNewChild(pptr, 0, "explainResponse", 0);
761             ns_srw = xmlNewNs(ptr, ns, "zs");
762             xmlSetNs(ptr, ns_srw);
763
764             add_xsd_string(ptr, "version", (*p)->srw_version);
765             if (1)
766             {
767                 xmlNodePtr ptr1 = xmlNewChild(ptr, 0, "record", 0);
768                 yaz_srw_record(o, ptr1, &res->record, client_data, ns);
769             }
770             if (res->num_diagnostics)
771             {
772                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "diagnostics", 0);
773                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
774                                     &res->num_diagnostics, client_data, ns);
775             }
776         }
777         else if ((*p)->which == Z_SRW_scan_request)
778         {
779             Z_SRW_scanRequest *req = (*p)->u.scan_request;
780             xmlNodePtr ptr = xmlNewChild(pptr, 0, "scanRequest", 0);
781             ns_srw = xmlNewNs(ptr, ns, "zs");
782             xmlSetNs(ptr, ns_srw);
783
784             add_xsd_string(ptr, "version", (*p)->srw_version);
785             add_xsd_string(ptr, "scanClause", req->scanClause);
786             add_xsd_integer(ptr, "responsePosition", req->responsePosition);
787             add_xsd_integer(ptr, "maximumTerms", req->maximumTerms);
788             add_xsd_string(ptr, "stylesheet", req->stylesheet);
789             add_xsd_string(ptr, "database", req->database);
790         }
791         else if ((*p)->which == Z_SRW_scan_response)
792         {
793             Z_SRW_scanResponse *res = (*p)->u.scan_response;
794             xmlNodePtr ptr = xmlNewChild(pptr, 0, "scanResponse", 0);
795             ns_srw = xmlNewNs(ptr, ns, "zs");
796             xmlSetNs(ptr, ns_srw);
797
798             add_xsd_string(ptr, "version", (*p)->srw_version);
799
800             if (res->num_terms)
801             {
802                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "terms", 0);
803                 yaz_srw_terms(o, rptr, &res->terms, &res->num_terms,
804                               client_data, ns);
805             }
806             if (res->num_diagnostics)
807             {
808                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "diagnostics", 0);
809                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
810                                     &res->num_diagnostics, client_data, ns);
811             }
812         }
813         else
814             return -1;
815
816     }
817     return 0;
818 }
819
820 #endif
821
822