Doxyfile file description. Indentation. No change of code.
[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.27 2004-10-15 00:19:00 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
582             for (; ptr; ptr = ptr->next)
583             {
584                 if (match_xsd_string(ptr, "version", o,
585                                            &(*p)->srw_version))
586                     ;
587                 else if (match_element(ptr, "record"))
588                     yaz_srw_record(o, ptr, &res->record, client_data, ns);
589                 else if (match_element(ptr, "diagnostics"))
590                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
591                                         &res->num_diagnostics,
592                                         client_data, ns);
593                 ;
594             }
595         }
596         else if (!strcmp(method->name, "scanRequest"))
597         {
598             Z_SRW_scanRequest *req;
599             xmlNodePtr ptr = method->children;
600
601             (*p)->which = Z_SRW_scan_request;
602             req = (*p)->u.scan_request = (Z_SRW_scanRequest *)
603                 odr_malloc(o, sizeof(*req));
604             req->database = 0;
605             req->scanClause = 0;
606             req->stylesheet = 0;
607             req->responsePosition = 0;
608             req->maximumTerms = 0;
609             
610             for (; ptr; ptr = ptr->next)
611             {
612                 if (match_xsd_string(ptr, "version", o,
613                                      &(*p)->srw_version))
614                     ;
615                 else if (match_xsd_string(ptr, "scanClause", o,
616                                      &req->scanClause))
617                     ;
618                 else if (match_xsd_integer(ptr, "responsePosition", o,
619                                            &req->responsePosition))
620                     ;
621                 else if (match_xsd_integer(ptr, "maximumTerms", o,
622                                            &req->maximumTerms))
623                     ;
624                 else if (match_xsd_string(ptr, "stylesheet", o,
625                                           &req->stylesheet))
626                     ;
627                 else if (match_xsd_string(ptr, "database", o,
628                                           &req->database))
629                     ;
630             }
631         }
632         else if (!strcmp(method->name, "scanResponse"))
633         {
634             Z_SRW_scanResponse *res;
635             xmlNodePtr ptr = method->children;
636
637             (*p)->which = Z_SRW_scan_response;
638             res = (*p)->u.scan_response = (Z_SRW_scanResponse *)
639                 odr_malloc(o, sizeof(*res));
640             res->terms = 0;
641             res->num_terms = 0;
642             res->diagnostics = 0;
643             res->num_diagnostics = 0;
644             
645             for (; ptr; ptr = ptr->next)
646             {
647                 if (match_xsd_string(ptr, "version", o,
648                                      &(*p)->srw_version))
649                     ;
650                 else if (match_element(ptr, "terms"))
651                     yaz_srw_terms(o, ptr, &res->terms,
652                                   &res->num_terms, client_data,
653                                   ns);
654                 else if (match_element(ptr, "diagnostics"))
655                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
656                                         &res->num_diagnostics,
657                                         client_data, ns);
658             }
659         }
660         else
661         {
662             *p = 0;
663             return -1;
664         }
665     }
666     else if (o->direction == ODR_ENCODE)
667     {
668         Z_SRW_PDU **p = handler_data;
669         xmlNsPtr ns_srw;
670         
671         if ((*p)->which == Z_SRW_searchRetrieve_request)
672         {
673             Z_SRW_searchRetrieveRequest *req = (*p)->u.request;
674             xmlNodePtr ptr = xmlNewChild(pptr, 0,
675                                          "searchRetrieveRequest", 0);
676             ns_srw = xmlNewNs(ptr, ns, "zs");
677             xmlSetNs(ptr, ns_srw);
678
679             if ((*p)->srw_version)
680                 add_xsd_string(ptr, "version", (*p)->srw_version);
681             switch(req->query_type)
682             {
683             case Z_SRW_query_type_cql:
684                 add_xsd_string(ptr, "query", req->query.cql);
685                 break;
686             case Z_SRW_query_type_xcql:
687                 add_xsd_string(ptr, "xQuery", req->query.xcql);
688                 break;
689             case Z_SRW_query_type_pqf:
690                 add_xsd_string(ptr, "pQuery", req->query.pqf);
691                 break;
692             }
693             add_xsd_integer(ptr, "startRecord", req->startRecord);
694             add_xsd_integer(ptr, "maximumRecords", req->maximumRecords);
695             add_xsd_string(ptr, "recordPacking", req->recordPacking);
696             add_xsd_string(ptr, "recordSchema", req->recordSchema);
697             add_xsd_string(ptr, "recordXPath", req->recordXPath);
698             add_xsd_integer(ptr, "resultSetTTL", req->resultSetTTL);
699             switch(req->sort_type)
700             {
701             case Z_SRW_sort_type_none:
702                 break;
703             case Z_SRW_sort_type_sort:
704                 add_xsd_string(ptr, "sortKeys", req->sort.sortKeys);
705                 break;
706             case Z_SRW_sort_type_xSort:
707                 add_xsd_string(ptr, "xSortKeys", req->sort.xSortKeys);
708                 break;
709             }
710             add_xsd_string(ptr, "stylesheet", req->stylesheet);
711             add_xsd_string(ptr, "database", req->database);
712         }
713         else if ((*p)->which == Z_SRW_searchRetrieve_response)
714         {
715             Z_SRW_searchRetrieveResponse *res = (*p)->u.response;
716             xmlNodePtr ptr = xmlNewChild(pptr, 0,
717                                          "searchRetrieveResponse", 0);
718             ns_srw = xmlNewNs(ptr, ns, "zs");
719             xmlSetNs(ptr, ns_srw);
720
721             if ((*p)->srw_version)
722                 add_xsd_string(ptr, "version", (*p)->srw_version);
723             add_xsd_integer(ptr, "numberOfRecords", res->numberOfRecords);
724             add_xsd_string(ptr, "resultSetId", res->resultSetId);
725             add_xsd_integer(ptr, "resultSetIdleTime", res->resultSetIdleTime);
726             if (res->num_records)
727             {
728                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "records", 0);
729                 yaz_srw_records(o, rptr, &res->records, &res->num_records,
730                                 client_data, ns);
731             }
732             add_xsd_integer(ptr, "nextRecordPosition",
733                             res->nextRecordPosition);
734             if (res->num_diagnostics)
735             {
736                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "diagnostics", 0);
737                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
738                                     &res->num_diagnostics, client_data, ns);
739             }
740         }
741         else if ((*p)->which == Z_SRW_explain_request)
742         {
743             Z_SRW_explainRequest *req = (*p)->u.explain_request;
744             xmlNodePtr ptr = xmlNewChild(pptr, 0, "explainRequest", 0);
745             ns_srw = xmlNewNs(ptr, ns, "zs");
746             xmlSetNs(ptr, ns_srw);
747
748             add_xsd_string(ptr, "version", (*p)->srw_version);
749             add_xsd_string(ptr, "recordPacking", req->recordPacking);
750             add_xsd_string(ptr, "stylesheet", req->stylesheet);
751             add_xsd_string(ptr, "database", req->database);
752         }
753         else if ((*p)->which == Z_SRW_explain_response)
754         {
755             Z_SRW_explainResponse *res = (*p)->u.explain_response;
756             xmlNodePtr ptr = xmlNewChild(pptr, 0, "explainResponse", 0);
757             ns_srw = xmlNewNs(ptr, ns, "zs");
758             xmlSetNs(ptr, ns_srw);
759
760             add_xsd_string(ptr, "version", (*p)->srw_version);
761             if (1)
762             {
763                 xmlNodePtr ptr1 = xmlNewChild(ptr, 0, "record", 0);
764                 yaz_srw_record(o, ptr1, &res->record, client_data, ns);
765             }
766             if (res->num_diagnostics)
767             {
768                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "diagnostics", 0);
769                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
770                                     &res->num_diagnostics, client_data, ns);
771             }
772         }
773         else if ((*p)->which == Z_SRW_scan_request)
774         {
775             Z_SRW_scanRequest *req = (*p)->u.scan_request;
776             xmlNodePtr ptr = xmlNewChild(pptr, 0, "scanRequest", 0);
777             ns_srw = xmlNewNs(ptr, ns, "zs");
778             xmlSetNs(ptr, ns_srw);
779
780             add_xsd_string(ptr, "version", (*p)->srw_version);
781             add_xsd_string(ptr, "scanClause", req->scanClause);
782             add_xsd_integer(ptr, "responsePosition", req->responsePosition);
783             add_xsd_integer(ptr, "maximumTerms", req->maximumTerms);
784             add_xsd_string(ptr, "stylesheet", req->stylesheet);
785             add_xsd_string(ptr, "database", req->database);
786         }
787         else if ((*p)->which == Z_SRW_scan_response)
788         {
789             Z_SRW_scanResponse *res = (*p)->u.scan_response;
790             xmlNodePtr ptr = xmlNewChild(pptr, 0, "scanResponse", 0);
791             ns_srw = xmlNewNs(ptr, ns, "zs");
792             xmlSetNs(ptr, ns_srw);
793
794             add_xsd_string(ptr, "version", (*p)->srw_version);
795
796             if (res->num_terms)
797             {
798                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "terms", 0);
799                 yaz_srw_terms(o, rptr, &res->terms, &res->num_terms,
800                               client_data, ns);
801             }
802             if (res->num_diagnostics)
803             {
804                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "diagnostics", 0);
805                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
806                                     &res->num_diagnostics, client_data, ns);
807             }
808         }
809         else
810             return -1;
811
812     }
813     return 0;
814 }
815
816 #endif
817
818