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