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