Fix sequence of diagnostic element
[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.18 2004-01-15 23:33:29 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 xmlNewChild(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         xmlNewChild(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 = 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 = odr_malloc(o, *num * sizeof(**recs));
286         for (i = 0; i < *num; i++)
287         {
288             (*recs)[i].code = 0;
289             (*recs)[i].details = 0;
290         } 
291         for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next)
292         {
293             if (ptr->type == XML_ELEMENT_NODE &&
294                 !strcmp(ptr->name, "diagnostic"))
295             {
296                 xmlNodePtr rptr;
297                 (*recs)[i].code = 0;
298                 (*recs)[i].details = 0;
299                 for (rptr = ptr->children; rptr; rptr = rptr->next)
300                 {
301                     if (match_xsd_integer(rptr, "code", o, 
302                                                &(*recs)[i].code))
303                         ;
304                     else if (match_xsd_string(rptr, "details", o, 
305                                               &(*recs)[i].details))
306                         ;
307                 }
308                 i++;
309             }
310         }
311     }
312     else if (o->direction == ODR_ENCODE)
313     {
314         int i;
315         xmlNsPtr ns_diag =
316             xmlNewNs(pptr, "http://www.loc.gov/zing/srw/diagnostics/", "diag");
317         for (i = 0; i < *num; i++)
318         {
319             xmlNodePtr rptr = xmlNewChild(pptr, ns_diag, "diagnostic", 0);
320             add_xsd_integer(rptr, "code", (*recs)[i].code);
321             if ((*recs)[i].code)
322             {
323                 const char *message = yaz_diag_srw_str(*(*recs)[i].code);
324                 if (message)
325                     add_xsd_string(rptr, "message", message);
326             }
327             add_xsd_string(rptr, "details", (*recs)[i].details);
328         }
329     }
330     return 0;
331 }
332
333 static int yaz_srw_term(ODR o, xmlNodePtr pptr, Z_SRW_scanTerm *term,
334                         void *client_data, const char *ns)
335 {
336     if (o->direction == ODR_DECODE)
337     {
338         xmlNodePtr ptr;
339         term->value = 0;
340         term->numberOfRecords = 0;
341         term->displayTerm = 0;
342         for (ptr = pptr->children; ptr; ptr = ptr->next)
343         {
344             if (match_xsd_string(ptr, "value", o,  &term->value))
345                 ;
346             else if (match_xsd_integer(ptr, "numberOfRecords", o, 
347                                    &term->numberOfRecords))
348                 ;
349             else if (match_xsd_string(ptr, "displayTerm", o, 
350                                       &term->displayTerm))
351                 ;
352         }
353     }
354     else if (o->direction == ODR_ENCODE)
355     {
356         xmlNodePtr ptr = pptr;
357         add_xsd_string(ptr, "value", term->value);
358         add_xsd_integer(ptr, "value", term->numberOfRecords);
359         add_xsd_string(ptr, "displayTerm", term->displayTerm);
360     }
361     return 0;
362 }
363
364 static int yaz_srw_terms(ODR o, xmlNodePtr pptr, Z_SRW_scanTerm **terms,
365                          int *num, void *client_data, const char *ns)
366 {
367     if (o->direction == ODR_DECODE)
368     {
369         int i;
370         xmlNodePtr ptr;
371         *num = 0;
372         for (ptr = pptr->children; ptr; ptr = ptr->next)
373         {
374             if (ptr->type == XML_ELEMENT_NODE &&
375                 !strcmp(ptr->name, "term"))
376                 (*num)++;
377         }
378         if (!*num)
379             return 1;
380         *terms = odr_malloc(o, *num * sizeof(**terms));
381         for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next, i++)
382         {
383             if (ptr->type == XML_ELEMENT_NODE &&
384                 !strcmp(ptr->name, "term"))
385                 yaz_srw_term(o, ptr, (*terms)+i, client_data, ns);
386         }
387     }
388     else if (o->direction == ODR_ENCODE)
389     {
390         int i;
391         for (i = 0; i < *num; i++)
392         {
393             xmlNodePtr rptr = xmlNewChild(pptr, 0, "term", 0);
394             yaz_srw_term(o, rptr, (*terms)+i, client_data, ns);
395         }
396     }
397     return 0;
398 }
399
400 int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
401                   void *client_data, const char *ns)
402 {
403     xmlNodePtr pptr = vptr;
404     if (o->direction == ODR_DECODE)
405     {
406         Z_SRW_PDU **p = handler_data;
407         xmlNodePtr method = pptr->children;
408
409         while (method && method->type == XML_TEXT_NODE)
410             method = method->next;
411         
412         if (!method)
413             return -1;
414         if (method->type != XML_ELEMENT_NODE)
415             return -1;
416
417         *p = odr_malloc(o, sizeof(**p));
418         (*p)->srw_version = odr_strdup(o, "1.1");
419         
420         if (!strcmp(method->name, "searchRetrieveRequest"))
421         {
422             xmlNodePtr ptr = method->children;
423             Z_SRW_searchRetrieveRequest *req;
424
425             (*p)->which = Z_SRW_searchRetrieve_request;
426             req = (*p)->u.request = odr_malloc(o, sizeof(*req));
427             req->query_type = Z_SRW_query_type_cql;
428             req->query.cql = 0;
429             req->sort_type = Z_SRW_sort_type_none;
430             req->sort.none = 0;
431             req->startRecord = 0;
432             req->maximumRecords = 0;
433             req->recordSchema = 0;
434             req->recordPacking = 0;
435             req->recordXPath = 0;
436             req->resultSetTTL = 0;
437             req->stylesheet = 0;
438             req->database = 0;
439
440             for (; ptr; ptr = ptr->next)
441             {
442                 if (match_xsd_string(ptr, "version", o,
443                                      &(*p)->srw_version))
444                     ;
445                 else if (match_xsd_string(ptr, "query", o, 
446                                      &req->query.cql))
447                     req->query_type = Z_SRW_query_type_cql;
448                 else if (match_xsd_string(ptr, "pQuery", o, 
449                                      &req->query.pqf))
450                     req->query_type = Z_SRW_query_type_pqf;
451                 else if (match_xsd_string(ptr, "xQuery", o, 
452                                      &req->query.xcql))
453                     req->query_type = Z_SRW_query_type_xcql;
454                 else if (match_xsd_integer(ptr, "startRecord", o,
455                                            &req->startRecord))
456                     ;
457                 else if (match_xsd_integer(ptr, "maximumRecords", o,
458                                            &req->maximumRecords))
459                     ;
460                 else if (match_xsd_string(ptr, "recordPacking", o,
461                                           &req->recordPacking))
462                     ;
463                 else if (match_xsd_string(ptr, "recordSchema", o, 
464                                           &req->recordSchema))
465                     ;
466                 else if (match_xsd_string(ptr, "recordXPath", o,
467                                           &req->recordXPath))
468                     ;
469                 else if (match_xsd_string(ptr, "resultSetTTL", o,
470                                            &req->database))
471                     ;
472                 else if (match_xsd_string(ptr, "sortKeys", o, 
473                                           &req->sort.sortKeys))
474                     req->sort_type = Z_SRW_sort_type_sort;
475                 else if (match_xsd_string(ptr, "stylesheet", o,
476                                            &req->stylesheet))
477                     ;
478                 else if (match_xsd_string(ptr, "database", o,
479                                            &req->database))
480                     ;
481                 /* missing is xQuery, xSortKeys .. */
482             }
483         }
484         else if (!strcmp(method->name, "searchRetrieveResponse"))
485         {
486             xmlNodePtr ptr = method->children;
487             Z_SRW_searchRetrieveResponse *res;
488
489             (*p)->which = Z_SRW_searchRetrieve_response;
490             res = (*p)->u.response = odr_malloc(o, sizeof(*res));
491
492             res->numberOfRecords = 0;
493             res->resultSetId = 0;
494             res->resultSetIdleTime = 0;
495             res->records = 0;
496             res->num_records = 0;
497             res->diagnostics = 0;
498             res->num_diagnostics = 0;
499             res->nextRecordPosition = 0;
500
501             for (; ptr; ptr = ptr->next)
502             {
503                 if (match_xsd_string(ptr, "version", o,
504                                      &(*p)->srw_version))
505                     ;
506                 else if (match_xsd_integer(ptr, "numberOfRecords", o, 
507                                       &res->numberOfRecords))
508                     ;
509                 else if (match_xsd_string(ptr, "resultSetId", o, 
510                                           &res->resultSetId))
511                     ;
512                 else if (match_xsd_integer(ptr, "resultSetIdleTime", o, 
513                                            &res->resultSetIdleTime))
514                     ;
515                 else if (match_element(ptr, "records"))
516                     yaz_srw_records(o, ptr, &res->records,
517                                     &res->num_records, client_data,
518                                     ns);
519                 else if (match_xsd_integer(ptr, "nextRecordPosition", o,
520                                            &res->nextRecordPosition))
521                     ;
522                 else if (match_element(ptr, "diagnostics"))
523                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
524                                         &res->num_diagnostics,
525                                         client_data, ns);
526             }
527         }
528         else if (!strcmp(method->name, "explainRequest"))
529         {
530             Z_SRW_explainRequest *req;
531             xmlNodePtr ptr = method->children;
532             
533             (*p)->which = Z_SRW_explain_request;
534             req = (*p)->u.explain_request = odr_malloc(o, sizeof(*req));
535             req->recordPacking = 0;
536             req->database = 0;
537             req->stylesheet = 0;
538             for (; ptr; ptr = ptr->next)
539             {
540                 if (match_xsd_string(ptr, "version", o,
541                                            &(*p)->srw_version))
542                     ;
543                 else if (match_xsd_string(ptr, "stylesheet", o,
544                                           &req->stylesheet))
545                     ;
546                 else if (match_xsd_string(ptr, "recordPacking", o,
547                                      &req->recordPacking))
548                     ;
549                 else if (match_xsd_string(ptr, "database", o,
550                                      &req->database))
551                     ;
552             }
553         }
554         else if (!strcmp(method->name, "explainResponse"))
555         {
556             Z_SRW_explainResponse *res;
557             xmlNodePtr ptr = method->children;
558
559             (*p)->which = Z_SRW_explain_response;
560             res = (*p)->u.explain_response = odr_malloc(o, sizeof(*res));
561             res->diagnostics = 0;
562             res->num_diagnostics = 0;
563
564             for (; ptr; ptr = ptr->next)
565             {
566                 if (match_xsd_string(ptr, "version", o,
567                                            &(*p)->srw_version))
568                     ;
569                 else if (match_element(ptr, "record"))
570                     yaz_srw_record(o, ptr, &res->record, client_data, ns);
571                 else if (match_element(ptr, "diagnostics"))
572                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
573                                         &res->num_diagnostics,
574                                         client_data, ns);
575                 ;
576             }
577         }
578         else if (!strcmp(method->name, "scanRequest"))
579         {
580             Z_SRW_scanRequest *req;
581             xmlNodePtr ptr = method->children;
582
583             (*p)->which = Z_SRW_scan_request;
584             req = (*p)->u.scan_request = odr_malloc(o, sizeof(*req));
585             req->database = 0;
586             req->scanClause = 0;
587             req->stylesheet = 0;
588             req->responsePosition = 0;
589             req->maximumTerms = 0;
590             
591             for (; ptr; ptr = ptr->next)
592             {
593                 if (match_xsd_string(ptr, "version", o,
594                                      &(*p)->srw_version))
595                     ;
596                 else if (match_xsd_string(ptr, "scanClause", o,
597                                      &req->scanClause))
598                     ;
599                 else if (match_xsd_integer(ptr, "responsePosition", o,
600                                            &req->responsePosition))
601                     ;
602                 else if (match_xsd_integer(ptr, "maximumTerms", o,
603                                            &req->maximumTerms))
604                     ;
605                 else if (match_xsd_string(ptr, "stylesheet", o,
606                                           &req->stylesheet))
607                     ;
608                 else if (match_xsd_string(ptr, "database", o,
609                                           &req->database))
610                     ;
611             }
612         }
613         else if (!strcmp(method->name, "scanResponse"))
614         {
615             Z_SRW_scanResponse *res;
616             xmlNodePtr ptr = method->children;
617
618             (*p)->which = Z_SRW_scan_response;
619             res = (*p)->u.scan_response = odr_malloc(o, sizeof(*res));
620             res->terms = 0;
621             res->num_terms = 0;
622             res->diagnostics = 0;
623             res->num_diagnostics = 0;
624             
625             for (; ptr; ptr = ptr->next)
626             {
627                 if (match_xsd_string(ptr, "version", o,
628                                      &(*p)->srw_version))
629                     ;
630                 else if (match_element(ptr, "terms"))
631                     yaz_srw_terms(o, ptr, &res->terms,
632                                   &res->num_terms, client_data,
633                                   ns);
634                 else if (match_element(ptr, "diagnostics"))
635                     yaz_srw_diagnostics(o, ptr, &res->diagnostics,
636                                         &res->num_diagnostics,
637                                         client_data, ns);
638             }
639         }
640         else
641         {
642             *p = 0;
643             return -1;
644         }
645     }
646     else if (o->direction == ODR_ENCODE)
647     {
648         Z_SRW_PDU **p = handler_data;
649         xmlNsPtr ns_srw;
650         
651         if ((*p)->which == Z_SRW_searchRetrieve_request)
652         {
653             Z_SRW_searchRetrieveRequest *req = (*p)->u.request;
654             xmlNodePtr ptr = xmlNewChild(pptr, 0,
655                                          "searchRetrieveRequest", 0);
656             ns_srw = xmlNewNs(ptr, ns, "zs");
657             xmlSetNs(ptr, ns_srw);
658
659             if ((*p)->srw_version)
660                 add_xsd_string(ptr, "version", (*p)->srw_version);
661             switch(req->query_type)
662             {
663             case Z_SRW_query_type_cql:
664                 add_xsd_string(ptr, "query", req->query.cql);
665                 break;
666             case Z_SRW_query_type_xcql:
667                 add_xsd_string(ptr, "xQuery", req->query.xcql);
668                 break;
669             case Z_SRW_query_type_pqf:
670                 add_xsd_string(ptr, "pQuery", req->query.pqf);
671                 break;
672             }
673             add_xsd_integer(ptr, "startRecord", req->startRecord);
674             add_xsd_integer(ptr, "maximumRecords", req->maximumRecords);
675             add_xsd_string(ptr, "recordPacking", req->recordPacking);
676             add_xsd_string(ptr, "recordSchema", req->recordSchema);
677             add_xsd_string(ptr, "recordXPath", req->recordXPath);
678             add_xsd_integer(ptr, "resultSetTTL", req->resultSetTTL);
679             switch(req->sort_type)
680             {
681             case Z_SRW_sort_type_none:
682                 break;
683             case Z_SRW_sort_type_sort:
684                 add_xsd_string(ptr, "sortKeys", req->sort.sortKeys);
685                 break;
686             case Z_SRW_sort_type_xSort:
687                 add_xsd_string(ptr, "xSortKeys", req->sort.xSortKeys);
688                 break;
689             }
690             add_xsd_string(ptr, "stylesheet", req->stylesheet);
691             add_xsd_string(ptr, "database", req->database);
692         }
693         else if ((*p)->which == Z_SRW_searchRetrieve_response)
694         {
695             Z_SRW_searchRetrieveResponse *res = (*p)->u.response;
696             xmlNodePtr ptr = xmlNewChild(pptr, 0,
697                                          "searchRetrieveResponse", 0);
698             ns_srw = xmlNewNs(ptr, ns, "zs");
699             xmlSetNs(ptr, ns_srw);
700
701             if ((*p)->srw_version)
702                 add_xsd_string(ptr, "version", (*p)->srw_version);
703             add_xsd_integer(ptr, "numberOfRecords", res->numberOfRecords);
704             add_xsd_string(ptr, "resultSetId", res->resultSetId);
705             add_xsd_integer(ptr, "resultSetIdleTime", res->resultSetIdleTime);
706             if (res->num_records)
707             {
708                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "records", 0);
709                 yaz_srw_records(o, rptr, &res->records, &res->num_records,
710                                 client_data, ns);
711             }
712             add_xsd_integer(ptr, "nextRecordPosition",
713                             res->nextRecordPosition);
714             if (res->num_diagnostics)
715             {
716                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "diagnostics", 0);
717                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
718                                     &res->num_diagnostics, client_data, ns);
719             }
720         }
721         else if ((*p)->which == Z_SRW_explain_request)
722         {
723             Z_SRW_explainRequest *req = (*p)->u.explain_request;
724             xmlNodePtr ptr = xmlNewChild(pptr, 0, "explainRequest", 0);
725             ns_srw = xmlNewNs(ptr, ns, "zs");
726             xmlSetNs(ptr, ns_srw);
727
728             add_xsd_string(ptr, "version", (*p)->srw_version);
729             add_xsd_string(ptr, "recordPacking", req->recordPacking);
730             add_xsd_string(ptr, "stylesheet", req->stylesheet);
731             add_xsd_string(ptr, "database", req->database);
732         }
733         else if ((*p)->which == Z_SRW_explain_response)
734         {
735             Z_SRW_explainResponse *res = (*p)->u.explain_response;
736             xmlNodePtr ptr = xmlNewChild(pptr, 0, "explainResponse", 0);
737             ns_srw = xmlNewNs(ptr, ns, "zs");
738             xmlSetNs(ptr, ns_srw);
739
740             add_xsd_string(ptr, "version", (*p)->srw_version);
741             if (1)
742             {
743                 xmlNodePtr ptr1 = xmlNewChild(ptr, 0, "record", 0);
744                 yaz_srw_record(o, ptr1, &res->record, client_data, ns);
745             }
746             if (res->num_diagnostics)
747             {
748                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "diagnostics", 0);
749                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
750                                     &res->num_diagnostics, client_data, ns);
751             }
752         }
753         else if ((*p)->which == Z_SRW_scan_request)
754         {
755             Z_SRW_scanRequest *req = (*p)->u.scan_request;
756             xmlNodePtr ptr = xmlNewChild(pptr, 0, "scanRequest", 0);
757             ns_srw = xmlNewNs(ptr, ns, "zs");
758             xmlSetNs(ptr, ns_srw);
759
760             add_xsd_string(ptr, "version", (*p)->srw_version);
761             add_xsd_string(ptr, "scanClause", req->scanClause);
762             add_xsd_integer(ptr, "responsePosition", req->responsePosition);
763             add_xsd_integer(ptr, "maximumTerms", req->maximumTerms);
764             add_xsd_string(ptr, "stylesheet", req->stylesheet);
765             add_xsd_string(ptr, "database", req->database);
766         }
767         else if ((*p)->which == Z_SRW_scan_response)
768         {
769             Z_SRW_scanResponse *res = (*p)->u.scan_response;
770             xmlNodePtr ptr = xmlNewChild(pptr, 0, "scanResponse", 0);
771             ns_srw = xmlNewNs(ptr, ns, "zs");
772             xmlSetNs(ptr, ns_srw);
773
774             add_xsd_string(ptr, "version", (*p)->srw_version);
775
776             if (res->num_terms)
777             {
778                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "terms", 0);
779                 yaz_srw_terms(o, rptr, &res->terms, &res->num_terms,
780                               client_data, ns);
781             }
782             if (res->num_diagnostics)
783             {
784                 xmlNodePtr rptr = xmlNewChild(ptr, 0, "diagnostics", 0);
785                 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
786                                     &res->num_diagnostics, client_data, ns);
787             }
788         }
789         else
790             return -1;
791
792     }
793     return 0;
794 }
795
796 #endif
797
798