yaz_query2xml complete and tested
[yaz-moved-to-github.git] / src / xmlquery.c
1 /*
2  * Copyright (C) 1995-2005, Index Data ApS
3  * All rights reserved.
4  *
5  * $Id: xmlquery.c,v 1.2 2006-01-30 14:02:07 adam Exp $
6  */
7
8 /**
9  * \file querytostr.c
10  * \brief Query / XML conversions
11  */
12
13 #include <stdio.h>
14 #include <assert.h>
15
16 #if HAVE_XML2
17 #include <libxml/parser.h>
18 #include <libxml/tree.h>
19
20 #include <yaz/logrpn.h>
21 #include <yaz/xmlquery.h>
22
23 void yaz_query2xml_attribute_element(const Z_AttributeElement *element,
24                                      xmlNodePtr parent)
25 {
26     char formstr[30];
27     const char *setname = 0;
28     
29     if (element->attributeSet)
30     {
31         oident *attrset;
32         attrset = oid_getentbyoid (element->attributeSet);
33         setname = attrset->desc;
34     }
35
36     if (element->which == Z_AttributeValue_numeric)
37     {
38         xmlNodePtr node = xmlNewChild(parent, 0, BAD_CAST "attr", 0);
39
40         if (setname)
41             xmlNewProp(node, BAD_CAST "set", BAD_CAST setname);
42
43         sprintf(formstr, "%d", *element->attributeType);
44         xmlNewProp(node, BAD_CAST "type", BAD_CAST formstr);
45
46         sprintf(formstr, "%d", *element->value.numeric);
47         xmlNewProp(node, BAD_CAST "value", BAD_CAST formstr);
48     }
49     else if (element->which == Z_AttributeValue_complex)
50     {
51         int i;
52         for (i = 0; i<element->value.complex->num_list; i++)
53         {
54             xmlNodePtr node = xmlNewChild(parent, 0, BAD_CAST "attr", 0);
55             
56             if (setname)
57                 xmlNewProp(node, BAD_CAST "set", BAD_CAST setname);
58             
59             sprintf(formstr, "%d", *element->attributeType);
60             xmlNewProp(node, BAD_CAST "type", BAD_CAST formstr);
61             
62             if (element->value.complex->list[i]->which ==
63                 Z_StringOrNumeric_string)
64             {
65                 xmlNewProp(node, BAD_CAST "value", BAD_CAST 
66                            element->value.complex->list[i]->u.string);
67             }
68             else if (element->value.complex->list[i]->which ==
69                      Z_StringOrNumeric_numeric)
70             {
71                 sprintf(formstr, "%d",
72                         *element->value.complex->list[i]->u.numeric);
73                 xmlNewProp(node, BAD_CAST "value", BAD_CAST formstr);
74             }
75         }
76     }
77 }
78
79
80 xmlNodePtr yaz_query2xml_term(const Z_Term *term,
81                               xmlNodePtr parent)
82 {
83     xmlNodePtr t = 0;
84     xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "term", 0);
85     char formstr[20];
86
87     switch (term->which)
88     {
89     case Z_Term_general:
90         t = xmlNewTextLen(BAD_CAST term->u.general->buf, term->u.general->len);
91         break;
92     case Z_Term_characterString:
93         t = xmlNewText(BAD_CAST term->u.characterString);
94         break;
95     case Z_Term_numeric:
96         sprintf(formstr, "%d", *term->u.numeric);
97         t = xmlNewText(BAD_CAST formstr);       
98         break;
99     case Z_Term_null:
100         break;
101     default:
102         break;
103     }
104     if (t) /* got a term node ? */
105         xmlAddChild(node, t);
106     return node;
107 }
108
109 xmlNodePtr yaz_query2xml_apt(const Z_AttributesPlusTerm *zapt,
110                              xmlNodePtr parent)
111 {
112     xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "apt", 0);
113     int num_attributes = zapt->attributes->num_attributes;
114     int i;
115     for (i = 0; i<num_attributes; i++)
116         yaz_query2xml_attribute_element(zapt->attributes->attributes[i], node);
117     yaz_query2xml_term(zapt->term, node);
118
119     return node;
120 }
121
122
123 void yaz_query2xml_operator(Z_Operator *op, xmlNodePtr node)
124 {
125     const char *type = 0;
126     switch(op->which)
127     {
128     case Z_Operator_and:
129         type = "and";
130         break;
131     case Z_Operator_or:
132         type = "or";
133         break;
134     case Z_Operator_and_not:
135         type = "not";
136         break;
137     case Z_Operator_prox:
138         type = "prox";
139         break;
140     default:
141         return;
142     }
143     xmlNewProp(node, BAD_CAST "type", BAD_CAST type);
144     
145     if (op->which == Z_Operator_prox)
146     {
147         char formstr[30];
148         
149         if (op->u.prox->exclusion)
150         {
151             if (*op->u.prox->exclusion)
152                 xmlNewProp(node, BAD_CAST "exclusion", BAD_CAST "true");
153             else
154                 xmlNewProp(node, BAD_CAST "exclusion", BAD_CAST "false");
155         }
156         sprintf(formstr, "%d", *op->u.prox->distance);
157         xmlNewProp(node, BAD_CAST "distance", BAD_CAST formstr);
158
159         if (*op->u.prox->ordered)
160             xmlNewProp(node, BAD_CAST "ordered", BAD_CAST "true");
161         else 
162             xmlNewProp(node, BAD_CAST "ordered", BAD_CAST "false");
163        
164         sprintf(formstr, "%d", *op->u.prox->relationType);
165         xmlNewProp(node, BAD_CAST "relationType", BAD_CAST formstr);
166         
167         switch(op->u.prox->which)
168         {
169         case Z_ProximityOperator_known:
170             sprintf(formstr, "%d", *op->u.prox->u.known);
171             xmlNewProp(node, BAD_CAST "knownProximityUnit",
172                        BAD_CAST formstr);
173             break;
174         default:
175             xmlNewProp(node, BAD_CAST "privateProximityUnit",
176                        BAD_CAST "private");
177             break;
178         }
179     }
180 }
181
182 xmlNodePtr yaz_query2xml_rpnstructure(const Z_RPNStructure *zs,
183                                       xmlNodePtr parent)
184 {
185     if (zs->which == Z_RPNStructure_complex)
186     {
187         Z_Complex *zc = zs->u.complex;
188
189         xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "binary", 0);
190         if (zc->roperator)
191             yaz_query2xml_operator(zc->roperator, node);
192         yaz_query2xml_rpnstructure(zc->s1, node);
193         yaz_query2xml_rpnstructure(zc->s2, node);
194         return node;
195     }
196     else if (zs->which == Z_RPNStructure_simple)
197     {
198         if (zs->u.simple->which == Z_Operand_APT)
199             return yaz_query2xml_apt(zs->u.simple->u.attributesPlusTerm,
200                                      parent);
201         else if (zs->u.simple->which == Z_Operand_resultSetId)
202             return xmlNewChild(parent, /* NS */ 0, BAD_CAST "rset", 
203                                BAD_CAST zs->u.simple->u.resultSetId);
204     }
205     return 0;
206 }
207
208 xmlNodePtr yaz_query2xml_rpn(const Z_RPNQuery *rpn, xmlNodePtr parent)
209 {
210     oident *attrset = oid_getentbyoid (rpn->attributeSetId);
211     if (attrset && attrset->value)
212         xmlNewProp(parent, BAD_CAST "set", BAD_CAST attrset->desc);
213     return yaz_query2xml_rpnstructure(rpn->RPNStructure, parent);
214 }
215
216 xmlNodePtr yaz_query2xml_ccl(const Odr_oct *ccl, xmlNodePtr node)
217 {
218     return 0;
219 }
220
221 xmlNodePtr yaz_query2xml_z3958(const Odr_oct *ccl, xmlNodePtr node)
222 {
223     return 0;
224 }
225
226 xmlNodePtr yaz_query2xml_cql(const char *cql, xmlNodePtr node)
227 {
228     return 0;
229 }
230
231 void yaz_rpnquery2xml(const Z_RPNQuery *rpn, void *docp_void)
232 {
233     Z_Query query;
234
235     query.which = Z_Query_type_1;
236     query.u.type_1 = (Z_RPNQuery *) rpn;
237     yaz_query2xml(&query, docp_void);
238 }
239
240 void yaz_query2xml(const Z_Query *q, void *docp_void)
241 {
242     xmlDocPtr *docp = (xmlDocPtr *) docp_void;
243     xmlNodePtr top_node, child_node = 0;
244     const char *type = 0;
245
246     assert(q);
247     assert(docp);
248
249     top_node = xmlNewNode(0, BAD_CAST "query");
250
251     switch (q->which)
252     {
253     case Z_Query_type_1: 
254     case Z_Query_type_101:
255         type = "rpn";
256         child_node = yaz_query2xml_rpn(q->u.type_1, top_node);
257         break;
258     case Z_Query_type_2:
259         type = "ccl";
260         child_node = yaz_query2xml_ccl(q->u.type_2, top_node);
261         break;
262     case Z_Query_type_100:
263         type = "z39.58";
264         child_node = yaz_query2xml_z3958(q->u.type_100, top_node);
265         break;
266     case Z_Query_type_104:
267         if (q->u.type_104->which == Z_External_CQL)
268         {
269             type = "cql";
270             child_node = yaz_query2xml_cql(q->u.type_104->u.cql, top_node);
271         }
272     }
273     
274     if (child_node && type)
275     {
276         *docp = xmlNewDoc(BAD_CAST "1.0");
277         xmlDocSetRootElement(*docp, top_node); /* make it top node in doc */
278
279         /* set type attribute now */
280         xmlNewProp(top_node, BAD_CAST "type", BAD_CAST type);
281     }
282     else
283     {
284         *docp = 0;
285         xmlFreeNode(top_node);
286     }
287 }
288
289 void yaz_xml2query(const xmlNode node, Z_Query **q, ODR odr)
290 {
291
292
293 }
294
295
296 /* HAVE_XML2 */
297 #endif
298
299 /*
300  * Local variables:
301  * c-basic-offset: 4
302  * indent-tabs-mode: nil
303  * End:
304  * vim: shiftwidth=4 tabstop=8 expandtab
305  */