Code updates which makes things compile as C++. Mostly type casts were
[yaz-moved-to-github.git] / src / xmlquery.c
1 /*
2  * Copyright (C) 1995-2007, Index Data ApS
3  * All rights reserved.
4  *
5  * $Id: xmlquery.c,v 1.15 2007-05-06 20:12:20 adam Exp $
6  */
7
8 /** \file xmlquery.c
9     \brief Query / XML conversions
10 */
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <assert.h>
15
16 #if YAZ_HAVE_XML2
17 #include <libxml/parser.h>
18 #include <libxml/tree.h>
19
20 #include <yaz/logrpn.h>
21 #include <yaz/xmlquery.h>
22 #include <yaz/nmem_xml.h>
23 #include <yaz/oid_db.h>
24
25 void yaz_query2xml_attribute_element(const Z_AttributeElement *element,
26                                      xmlNodePtr parent)
27 {
28     char formstr[30];
29     const char *setname = 0;
30     char oid_name_str[OID_STR_MAX];
31     
32     if (element->attributeSet)
33     {
34         setname = yaz_oid_to_string_buf(element->attributeSet,
35                                         0, oid_name_str);
36     }
37
38     if (element->which == Z_AttributeValue_numeric)
39     {
40         xmlNodePtr node = xmlNewChild(parent, 0, BAD_CAST "attr", 0);
41
42         if (setname)
43             xmlNewProp(node, BAD_CAST "set", BAD_CAST setname);
44
45         sprintf(formstr, "%d", *element->attributeType);
46         xmlNewProp(node, BAD_CAST "type", BAD_CAST formstr);
47
48         sprintf(formstr, "%d", *element->value.numeric);
49         xmlNewProp(node, BAD_CAST "value", BAD_CAST formstr);
50     }
51     else if (element->which == Z_AttributeValue_complex)
52     {
53         int i;
54         for (i = 0; i<element->value.complex->num_list; i++)
55         {
56             xmlNodePtr node = xmlNewChild(parent, 0, BAD_CAST "attr", 0);
57             
58             if (setname)
59                 xmlNewProp(node, BAD_CAST "set", BAD_CAST setname);
60             
61             sprintf(formstr, "%d", *element->attributeType);
62             xmlNewProp(node, BAD_CAST "type", BAD_CAST formstr);
63             
64             if (element->value.complex->list[i]->which ==
65                 Z_StringOrNumeric_string)
66             {
67                 xmlNewProp(node, BAD_CAST "value", BAD_CAST 
68                            element->value.complex->list[i]->u.string);
69             }
70             else if (element->value.complex->list[i]->which ==
71                      Z_StringOrNumeric_numeric)
72             {
73                 sprintf(formstr, "%d",
74                         *element->value.complex->list[i]->u.numeric);
75                 xmlNewProp(node, BAD_CAST "value", BAD_CAST formstr);
76             }
77         }
78     }
79 }
80
81
82 xmlNodePtr yaz_query2xml_term(const Z_Term *term,
83                               xmlNodePtr parent)
84 {
85     xmlNodePtr t = 0;
86     xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "term", 0);
87     char formstr[20];
88     const char *type = 0;
89
90     switch (term->which)
91     {
92     case Z_Term_general:
93         type = "general";
94         t = xmlNewTextLen(BAD_CAST term->u.general->buf, term->u.general->len);
95         break;
96     case Z_Term_numeric:
97         type = "numeric";
98         sprintf(formstr, "%d", *term->u.numeric);
99         t = xmlNewText(BAD_CAST formstr);       
100         break;
101     case Z_Term_characterString:
102         type = "string";
103         t = xmlNewText(BAD_CAST term->u.characterString);
104         break;
105     case Z_Term_oid:
106         type = "oid";
107         break;
108     case Z_Term_dateTime:
109         type = "dateTime";
110         break;
111     case Z_Term_external:
112         type = "external";
113         break;
114     case Z_Term_integerAndUnit:
115         type ="integerAndUnit";
116         break;
117     case Z_Term_null:
118         type = "null";
119         break;
120     default:
121         break;
122     }
123     if (t) /* got a term node ? */
124         xmlAddChild(node, t);
125     if (type)
126         xmlNewProp(node, BAD_CAST "type", BAD_CAST type);
127     return node;
128 }
129
130 xmlNodePtr yaz_query2xml_apt(const Z_AttributesPlusTerm *zapt,
131                              xmlNodePtr parent)
132 {
133     xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "apt", 0);
134     int num_attributes = zapt->attributes->num_attributes;
135     int i;
136     for (i = 0; i<num_attributes; i++)
137         yaz_query2xml_attribute_element(zapt->attributes->attributes[i], node);
138     yaz_query2xml_term(zapt->term, node);
139
140     return node;
141 }
142
143
144 void yaz_query2xml_operator(Z_Operator *op, xmlNodePtr node)
145 {
146     const char *type = 0;
147     switch(op->which)
148     {
149     case Z_Operator_and:
150         type = "and";
151         break;
152     case Z_Operator_or:
153         type = "or";
154         break;
155     case Z_Operator_and_not:
156         type = "not";
157         break;
158     case Z_Operator_prox:
159         type = "prox";
160         break;
161     default:
162         return;
163     }
164     xmlNewProp(node, BAD_CAST "type", BAD_CAST type);
165     
166     if (op->which == Z_Operator_prox)
167     {
168         char formstr[30];
169         
170         if (op->u.prox->exclusion)
171         {
172             if (*op->u.prox->exclusion)
173                 xmlNewProp(node, BAD_CAST "exclusion", BAD_CAST "true");
174             else
175                 xmlNewProp(node, BAD_CAST "exclusion", BAD_CAST "false");
176         }
177         sprintf(formstr, "%d", *op->u.prox->distance);
178         xmlNewProp(node, BAD_CAST "distance", BAD_CAST formstr);
179
180         if (*op->u.prox->ordered)
181             xmlNewProp(node, BAD_CAST "ordered", BAD_CAST "true");
182         else 
183             xmlNewProp(node, BAD_CAST "ordered", BAD_CAST "false");
184        
185         sprintf(formstr, "%d", *op->u.prox->relationType);
186         xmlNewProp(node, BAD_CAST "relationType", BAD_CAST formstr);
187         
188         switch(op->u.prox->which)
189         {
190         case Z_ProximityOperator_known:
191             sprintf(formstr, "%d", *op->u.prox->u.known);
192             xmlNewProp(node, BAD_CAST "knownProximityUnit",
193                        BAD_CAST formstr);
194             break;
195         case Z_ProximityOperator_private:
196         default:
197             xmlNewProp(node, BAD_CAST "privateProximityUnit",
198                        BAD_CAST "private");
199             break;
200         }
201     }
202 }
203
204 xmlNodePtr yaz_query2xml_rpnstructure(const Z_RPNStructure *zs,
205                                       xmlNodePtr parent)
206 {
207     if (zs->which == Z_RPNStructure_complex)
208     {
209         Z_Complex *zc = zs->u.complex;
210
211         xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "operator", 0);
212         if (zc->roperator)
213             yaz_query2xml_operator(zc->roperator, node);
214         yaz_query2xml_rpnstructure(zc->s1, node);
215         yaz_query2xml_rpnstructure(zc->s2, node);
216         return node;
217     }
218     else if (zs->which == Z_RPNStructure_simple)
219     {
220         if (zs->u.simple->which == Z_Operand_APT)
221             return yaz_query2xml_apt(zs->u.simple->u.attributesPlusTerm,
222                                      parent);
223         else if (zs->u.simple->which == Z_Operand_resultSetId)
224             return xmlNewChild(parent, /* NS */ 0, BAD_CAST "rset", 
225                                BAD_CAST zs->u.simple->u.resultSetId);
226     }
227     return 0;
228 }
229
230 xmlNodePtr yaz_query2xml_rpn(const Z_RPNQuery *rpn, xmlNodePtr parent)
231 {
232     if (rpn->attributeSetId)
233     {
234         char oid_name_str[OID_STR_MAX];
235         const char *setname = yaz_oid_to_string_buf(rpn->attributeSetId,
236                                                     0, oid_name_str);
237         if (setname)
238             xmlNewProp(parent, BAD_CAST "set", BAD_CAST setname);
239     }
240     return yaz_query2xml_rpnstructure(rpn->RPNStructure, parent);
241 }
242
243 xmlNodePtr yaz_query2xml_ccl(const Odr_oct *ccl, xmlNodePtr node)
244 {
245     return 0;
246 }
247
248 xmlNodePtr yaz_query2xml_z3958(const Odr_oct *ccl, xmlNodePtr node)
249 {
250     return 0;
251 }
252
253 xmlNodePtr yaz_query2xml_cql(const char *cql, xmlNodePtr node)
254 {
255     return 0;
256 }
257
258 void yaz_rpnquery2xml(const Z_RPNQuery *rpn, xmlDocPtr *docp)
259 {
260     Z_Query query;
261
262     query.which = Z_Query_type_1;
263     query.u.type_1 = (Z_RPNQuery *) rpn;
264     yaz_query2xml(&query, docp);
265 }
266
267 void yaz_query2xml(const Z_Query *q, xmlDocPtr *docp)
268 {
269     xmlNodePtr top_node, q_node = 0, child_node = 0;
270
271     assert(q);
272     assert(docp);
273
274     top_node = xmlNewNode(0, BAD_CAST "query");
275
276     switch (q->which)
277     {
278     case Z_Query_type_1: 
279     case Z_Query_type_101:
280         q_node = xmlNewChild(top_node, 0, BAD_CAST "rpn", 0);
281         child_node = yaz_query2xml_rpn(q->u.type_1, q_node);
282         break;
283     case Z_Query_type_2:
284         q_node = xmlNewChild(top_node, 0, BAD_CAST "ccl", 0);
285         child_node = yaz_query2xml_ccl(q->u.type_2, q_node);
286         break;
287     case Z_Query_type_100:
288         q_node = xmlNewChild(top_node, 0, BAD_CAST "z39.58", 0);
289         child_node = yaz_query2xml_z3958(q->u.type_100, q_node);
290         break;
291     case Z_Query_type_104:
292         if (q->u.type_104->which == Z_External_CQL)
293         {
294             q_node = xmlNewChild(top_node, 0, BAD_CAST "cql", 0);
295             child_node = yaz_query2xml_cql(q->u.type_104->u.cql, q_node);
296         }
297     }
298     if (child_node && q_node)
299     {
300         *docp = xmlNewDoc(BAD_CAST "1.0");
301         xmlDocSetRootElement(*docp, top_node); /* make it top node in doc */
302     }
303     else
304     {
305         *docp = 0;
306         xmlFreeNode(top_node);
307     }
308 }
309
310 bool_t *boolVal(ODR odr, const char *str)
311 {
312     if (*str == '\0' || strchr("0fF", *str))
313         return odr_intdup(odr, 0);
314     return odr_intdup(odr, 1);
315 }
316
317 int *intVal(ODR odr, const char *str)
318 {
319     return odr_intdup(odr, atoi(str));
320 }
321
322 void yaz_xml2query_operator(const xmlNode *ptr, Z_Operator **op,
323                             ODR odr, int *error_code, const char **addinfo)
324 {
325     const char *type = (const char *)
326         xmlGetProp((xmlNodePtr) ptr, BAD_CAST "type");
327     if (!type)
328     {
329         *error_code = 1;
330         *addinfo = "no operator type";
331         return;
332     }
333     *op = (Z_Operator*) odr_malloc(odr, sizeof(Z_Operator));
334     if (!strcmp(type, "and"))
335     {
336         (*op)->which = Z_Operator_and;
337         (*op)->u.op_and = odr_nullval();
338     }
339     else if (!strcmp(type, "or"))
340     {
341         (*op)->which = Z_Operator_or;
342         (*op)->u.op_or = odr_nullval();
343     }
344     else if (!strcmp(type, "not"))
345     {
346         (*op)->which = Z_Operator_and_not;
347         (*op)->u.and_not = odr_nullval();
348     }
349     else if (!strcmp(type, "prox"))
350     {
351         const char *atval;
352         Z_ProximityOperator *pop = (Z_ProximityOperator *) 
353             odr_malloc(odr, sizeof(Z_ProximityOperator));
354
355         (*op)->which = Z_Operator_prox;
356         (*op)->u.prox = pop;
357
358         atval = (const char *) xmlGetProp((xmlNodePtr) ptr,
359                                           BAD_CAST "exclusion");
360         if (atval)
361             pop->exclusion = boolVal(odr, atval);
362         else
363             pop->exclusion = 0;
364
365         atval = (const char *) xmlGetProp((xmlNodePtr) ptr,
366                                           BAD_CAST "distance");
367         if (atval)
368             pop->distance = intVal(odr, atval);
369         else
370             pop->distance = odr_intdup(odr, 1);
371
372         atval = (const char *) xmlGetProp((xmlNodePtr) ptr,
373                                           BAD_CAST "ordered");
374         if (atval)
375             pop->ordered = boolVal(odr, atval);
376         else
377             pop->ordered = odr_intdup(odr, 1);
378
379         atval = (const char *) xmlGetProp((xmlNodePtr) ptr,
380                                           BAD_CAST "relationType");
381         if (atval)
382             pop->relationType = intVal(odr, atval);
383         else
384             pop->relationType =
385                 odr_intdup(odr, Z_ProximityOperator_Prox_lessThanOrEqual);
386
387         atval = (const char *) xmlGetProp((xmlNodePtr) ptr,
388                                           BAD_CAST "knownProximityUnit");
389         if (atval)
390         {
391             pop->which = Z_ProximityOperator_known;            
392             pop->u.known = intVal(odr, atval);
393         }
394         else
395         {
396             pop->which = Z_ProximityOperator_known;
397             pop->u.known = odr_intdup(odr, Z_ProxUnit_word);
398         }
399
400         atval = (const char *) xmlGetProp((xmlNodePtr) ptr,
401                                           BAD_CAST "privateProximityUnit");
402         if (atval)
403         {
404             pop->which = Z_ProximityOperator_private;
405             pop->u.zprivate = intVal(odr, atval);
406         }
407     }
408     else
409     {
410         *error_code = 1;
411         *addinfo = "bad operator type";
412     }
413 }
414
415 void yaz_xml2query_attribute_element(const xmlNode *ptr, 
416                                      Z_AttributeElement **elem, ODR odr,
417                                      int *error_code, const char **addinfo)
418 {
419     int i;
420     xmlChar *set = 0;
421     xmlChar *type = 0;
422     xmlChar *value = 0;
423     int num_values = 0;
424     struct _xmlAttr *attr;
425     for (attr = ptr->properties; attr; attr = attr->next)
426     {
427         if (!xmlStrcmp(attr->name, BAD_CAST "set") &&
428             attr->children && attr->children->type == XML_TEXT_NODE)
429             set = attr->children->content;
430         else if (!xmlStrcmp(attr->name, BAD_CAST "type") &&
431             attr->children && attr->children->type == XML_TEXT_NODE)
432             type = attr->children->content;
433         else if (!xmlStrcmp(attr->name, BAD_CAST "value") &&
434             attr->children && attr->children->type == XML_TEXT_NODE)
435         {
436             value = attr->children->content;
437             num_values++;
438         }
439         else
440         {
441             *error_code = 1;
442             *addinfo = "bad attribute for attr content";
443             return;
444         }
445     }
446     if (!type)
447     {
448         *error_code = 1;
449         *addinfo = "missing type attribute for att content";
450         return;
451     }
452     if (!value)
453     {
454         *error_code = 1;
455         *addinfo = "missing value attribute for att content";
456         return;
457     }
458         
459     *elem = (Z_AttributeElement *) odr_malloc(odr, sizeof(**elem));
460     if (set)
461         (*elem)->attributeSet = yaz_string_to_oid_odr(yaz_oid_std(),
462                                                       CLASS_ATTSET,
463                                                       (const char *) set,
464                                                       odr);
465     else
466         (*elem)->attributeSet = 0;
467     (*elem)->attributeType = intVal(odr, (const char *) type);
468
469     /* looks like a number ? */
470     for (i = 0; value[i] && value[i] >= '0' && value[i] <= '9'; i++)
471         ;
472     if (num_values > 1 || value[i])
473     {   /* multiple values or string, so turn to complex attribute */
474         (*elem)->which = Z_AttributeValue_complex;
475         (*elem)->value.complex =
476             (Z_ComplexAttribute*) odr_malloc(odr, sizeof(Z_ComplexAttribute));
477         (*elem)->value.complex->num_list = num_values;
478         (*elem)->value.complex->list = (Z_StringOrNumeric **)
479             odr_malloc(odr, sizeof(Z_StringOrNumeric*) * num_values);
480
481         /* second pass over attr values */
482         i = 0;
483         for (attr = ptr->properties; attr; attr = attr->next)
484         {
485             if (!xmlStrcmp(attr->name, BAD_CAST "value") &&
486                 attr->children && attr->children->type == XML_TEXT_NODE)
487             {
488                 const char *val = (const char *) attr->children->content;
489                 assert (i < num_values);
490                 (*elem)->value.complex->list[i] = (Z_StringOrNumeric *)
491                     odr_malloc(odr, sizeof(Z_StringOrNumeric));
492                 (*elem)->value.complex->list[i]->which =
493                     Z_StringOrNumeric_string;
494                 (*elem)->value.complex->list[i]->u.string =
495                     odr_strdup(odr, val);
496                 i++;
497             }
498         }
499         (*elem)->value.complex->num_semanticAction = 0;
500         (*elem)->value.complex->semanticAction = 0;        
501     }
502     else
503     {   /* good'ld numeric value */
504         (*elem)->which = Z_AttributeValue_numeric;
505         (*elem)->value.numeric = intVal(odr, (const char *) value);
506     }
507 }
508
509 char *strVal(const xmlNode *ptr_cdata, ODR odr)
510 {
511     return nmem_text_node_cdata(ptr_cdata, odr_getmem(odr));
512 }
513
514 void yaz_xml2query_term(const xmlNode *ptr,
515                        Z_Term **term, ODR odr,
516                        int *error_code, const char **addinfo)
517 {
518     xmlChar *type = 0;
519     struct _xmlAttr *attr;
520     char *cdata = strVal(ptr->children, odr);
521
522     for (attr = ptr->properties; attr; attr = attr->next)
523     {
524         if (!xmlStrcmp(attr->name, BAD_CAST "type") &&
525             attr->children && attr->children->type == XML_TEXT_NODE)
526             type = attr->children->content;
527         else
528         {
529             *error_code = 1;
530             *addinfo = "bad attribute for attr content";
531             return;
532         }
533     }
534     *term = (Z_Term *) odr_malloc(odr, sizeof(Z_Term));
535
536     if (!type || !xmlStrcmp(type, BAD_CAST "general"))
537     {
538         (*term)->which = Z_Term_general;
539         (*term)->u.general =
540             odr_create_Odr_oct(odr, (unsigned char *)cdata, strlen(cdata));
541     }
542     else if (!xmlStrcmp(type, BAD_CAST "numeric"))
543     {
544         (*term)->which = Z_Term_numeric;
545         (*term)->u.numeric = intVal(odr, cdata);
546     }
547     else if (!xmlStrcmp(type, BAD_CAST "string"))
548     {
549         (*term)->which = Z_Term_characterString;
550         (*term)->u.characterString = cdata;
551     }
552     else if (!xmlStrcmp(type, BAD_CAST "oid"))
553     {
554         *error_code = 1;
555         *addinfo = "unhandled term type: oid";
556     }
557     else if (!xmlStrcmp(type, BAD_CAST "dateTime"))
558     {
559         *error_code = 1;
560         *addinfo = "unhandled term type: dateTime";
561     }
562     else if (!xmlStrcmp(type, BAD_CAST "integerAndUnit"))
563     {
564         *error_code = 1;
565         *addinfo = "unhandled term type: integerAndUnit";
566     }
567     else if (!xmlStrcmp(type, BAD_CAST "null"))
568     {
569         (*term)->which = Z_Term_null;
570         (*term)->u.null = odr_nullval();
571     }
572     else
573     {
574         *error_code = 1;
575         *addinfo = "unhandled term type";
576     }
577 }
578
579 void yaz_xml2query_apt(const xmlNode *ptr_apt,
580                        Z_AttributesPlusTerm **zapt, ODR odr,
581                        int *error_code, const char **addinfo)
582 {
583     const xmlNode *ptr = ptr_apt->children;
584     int i, num_attr = 0;
585
586     *zapt = (Z_AttributesPlusTerm *)
587         odr_malloc(odr, sizeof(Z_AttributesPlusTerm));
588
589     /* deal with attributes */
590     (*zapt)->attributes = (Z_AttributeList*)
591         odr_malloc(odr, sizeof(Z_AttributeList));
592
593     /* how many attributes? */
594     for (; ptr; ptr = ptr->next)
595         if (ptr->type == XML_ELEMENT_NODE)
596         {
597             if (!xmlStrcmp(ptr->name, BAD_CAST "attr"))
598                 num_attr++;
599             else
600                 break;
601         }
602
603     /* allocate and parse for real */
604     (*zapt)->attributes->num_attributes = num_attr;
605     (*zapt)->attributes->attributes = (Z_AttributeElement **)
606         odr_malloc(odr, sizeof(Z_AttributeElement*) * num_attr);
607
608     i = 0;    
609     ptr = ptr_apt->children;
610     for (; ptr; ptr = ptr->next)
611         if (ptr->type == XML_ELEMENT_NODE)
612         {
613             if (!xmlStrcmp(ptr->name, BAD_CAST "attr"))
614             {
615                 yaz_xml2query_attribute_element(
616                     ptr,  &(*zapt)->attributes->attributes[i], odr,
617                     error_code, addinfo);
618                 i++;
619             }
620             else
621                 break;
622         }
623     if (ptr && ptr->type == XML_ELEMENT_NODE)
624     {
625         if (!xmlStrcmp(ptr->name, BAD_CAST "term"))
626         {        
627             /* deal with term */
628             yaz_xml2query_term(ptr, &(*zapt)->term, odr, error_code, addinfo);
629         }
630         else
631         {
632             *error_code = 1;
633             *addinfo = "bad element in apt content";
634         }
635     }
636     else
637     {
638         *error_code = 1;
639         *addinfo = "missing term node in apt content";
640     }
641 }
642
643 void yaz_xml2query_rset(const xmlNode *ptr, Z_ResultSetId **rset,
644                         ODR odr, int *error_code, const char **addinfo)
645 {
646     if (ptr->children)
647     {
648         *rset = strVal(ptr->children, odr);
649     }
650     else
651     {
652         *error_code = 1;
653         *addinfo = "missing rset content";
654     }
655 }
656
657 void yaz_xml2query_rpnstructure(const xmlNode *ptr, Z_RPNStructure **zs,
658                                 ODR odr, int *error_code, const char **addinfo)
659 {
660     while (ptr && ptr->type != XML_ELEMENT_NODE)
661         ptr = ptr->next;
662     
663     if (!ptr || ptr->type != XML_ELEMENT_NODE)
664     {
665         *error_code = 1;
666         *addinfo = "missing rpn operator, rset, apt node";
667         return;
668     }
669     *zs = (Z_RPNStructure *) odr_malloc(odr, sizeof(Z_RPNStructure));
670     if (!xmlStrcmp(ptr->name, BAD_CAST "operator"))
671     {
672         Z_Complex *zc = (Z_Complex *) odr_malloc(odr, sizeof(Z_Complex));
673         
674         (*zs)->which = Z_RPNStructure_complex;
675         (*zs)->u.complex = zc;
676         
677         yaz_xml2query_operator(ptr, &zc->roperator, odr, error_code, addinfo);
678
679         ptr = ptr->children;
680         while (ptr && ptr->type != XML_ELEMENT_NODE)
681             ptr = ptr->next;
682         yaz_xml2query_rpnstructure(ptr, &zc->s1, odr, error_code, addinfo);
683         if (ptr)
684             ptr = ptr->next;
685         while (ptr && ptr->type != XML_ELEMENT_NODE)
686             ptr = ptr->next;
687         yaz_xml2query_rpnstructure(ptr, &zc->s2, odr, error_code, addinfo);
688     }
689     else 
690     {
691         Z_Operand *s = (Z_Operand *) odr_malloc(odr, sizeof(Z_Operand));
692         (*zs)->which = Z_RPNStructure_simple;
693         (*zs)->u.simple = s;
694         if (!xmlStrcmp(ptr->name, BAD_CAST "apt"))
695         {
696             s->which = Z_Operand_APT;
697             yaz_xml2query_apt(ptr, &s->u.attributesPlusTerm,
698                               odr, error_code, addinfo);
699         }
700         else if (!xmlStrcmp(ptr->name, BAD_CAST "rset"))
701         {
702             s->which = Z_Operand_resultSetId; 
703             yaz_xml2query_rset(ptr, &s->u.resultSetId,
704                                odr, error_code, addinfo);
705         }
706         else
707         {
708             *error_code = 1;
709             *addinfo = "bad element: expected binary, apt or rset";
710         }        
711     }
712 }
713
714 void yaz_xml2query_rpn(const xmlNode *ptr, Z_RPNQuery **query, ODR odr,
715                    int *error_code, const char **addinfo)
716 {
717     const char *set = (const char *)
718         xmlGetProp((xmlNodePtr) ptr, BAD_CAST "set");
719
720     *query = (Z_RPNQuery*) odr_malloc(odr, sizeof(Z_RPNQuery));
721     if (set)
722         (*query)->attributeSetId = yaz_string_to_oid_odr(yaz_oid_std(),
723                                                          CLASS_ATTSET, set, odr);
724     else
725         (*query)->attributeSetId = 0;
726     yaz_xml2query_rpnstructure(ptr->children, &(*query)->RPNStructure,
727                                odr, error_code, addinfo);
728 }
729
730 static void yaz_xml2query_(const xmlNode *ptr, Z_Query **query, ODR odr,
731                            int *error_code, const char **addinfo)
732 {
733     if (ptr && ptr->type == XML_ELEMENT_NODE && 
734         !xmlStrcmp(ptr->name, BAD_CAST "query"))
735     {
736         const char *type;
737         ptr = ptr->children;
738         while (ptr && ptr->type != XML_ELEMENT_NODE)
739             ptr = ptr->next;
740         if (!ptr || ptr->type != XML_ELEMENT_NODE)
741         {
742             *error_code = 1;
743             *addinfo = "missing query content";
744             return;
745         }
746         type = (const char *) ptr->name;
747
748         *query = (Z_Query*) odr_malloc(odr, sizeof(Z_Query));
749         if (!type || !strcmp(type, "rpn"))
750         {
751             (*query)->which = Z_Query_type_1;
752             yaz_xml2query_rpn(ptr, &(*query)->u.type_1, odr,
753                               error_code, addinfo);
754         }
755         else if (!strcmp(type, "ccl"))
756         {
757             *error_code = 1;
758             *addinfo = "ccl not supported yet";
759         }
760         else if (!strcmp(type, "z39.58"))
761         {
762             *error_code = 1;
763             *addinfo = "z39.58 not supported yet";
764         }
765         else if (!strcmp(type, "cql"))
766         {
767             *error_code = 1;
768             *addinfo = "cql not supported yet";
769         }
770         else
771         {
772             *error_code = 1;
773             *addinfo = "unsupported query type";
774         }
775     }
776     else
777     {
778         *error_code = 1;
779         *addinfo = "missing query element";
780     }
781 }
782
783 void yaz_xml2query(const xmlNode *xmlnodep, Z_Query **query, ODR odr,
784                    int *error_code, const char **addinfo)
785 {
786     yaz_xml2query_(xmlnodep, query, odr, error_code, addinfo);
787 }
788
789 /* YAZ_HAVE_XML2 */
790 #endif
791
792 /*
793  * Local variables:
794  * c-basic-offset: 4
795  * indent-tabs-mode: nil
796  * End:
797  * vim: shiftwidth=4 tabstop=8 expandtab
798  */