Supply Term type as attribute in XML RPN representation.
[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.3 2006-02-02 15:00:58 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     const char *type = 0;
87
88     switch (term->which)
89     {
90     case Z_Term_general:
91         type = "general";
92         t = xmlNewTextLen(BAD_CAST term->u.general->buf, term->u.general->len);
93         break;
94     case Z_Term_numeric:
95         type = "numeric";
96         sprintf(formstr, "%d", *term->u.numeric);
97         t = xmlNewText(BAD_CAST formstr);       
98         break;
99     case Z_Term_characterString:
100         type = "string";
101         t = xmlNewText(BAD_CAST term->u.characterString);
102         break;
103     case Z_Term_oid:
104         type = "oid";
105         break;
106     case Z_Term_dateTime:
107         type = "dateTime";
108         break;
109     case Z_Term_external:
110         type = "external";
111         break;
112     case Z_Term_integerAndUnit:
113         type ="integerAndUnit";
114         break;
115     case Z_Term_null:
116         type = "null";
117         break;
118     default:
119         break;
120     }
121     if (t) /* got a term node ? */
122         xmlAddChild(node, t);
123     if (type)
124         xmlNewProp(node, BAD_CAST "type", BAD_CAST type);
125     return node;
126 }
127
128 xmlNodePtr yaz_query2xml_apt(const Z_AttributesPlusTerm *zapt,
129                              xmlNodePtr parent)
130 {
131     xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "apt", 0);
132     int num_attributes = zapt->attributes->num_attributes;
133     int i;
134     for (i = 0; i<num_attributes; i++)
135         yaz_query2xml_attribute_element(zapt->attributes->attributes[i], node);
136     yaz_query2xml_term(zapt->term, node);
137
138     return node;
139 }
140
141
142 void yaz_query2xml_operator(Z_Operator *op, xmlNodePtr node)
143 {
144     const char *type = 0;
145     switch(op->which)
146     {
147     case Z_Operator_and:
148         type = "and";
149         break;
150     case Z_Operator_or:
151         type = "or";
152         break;
153     case Z_Operator_and_not:
154         type = "not";
155         break;
156     case Z_Operator_prox:
157         type = "prox";
158         break;
159     default:
160         return;
161     }
162     xmlNewProp(node, BAD_CAST "type", BAD_CAST type);
163     
164     if (op->which == Z_Operator_prox)
165     {
166         char formstr[30];
167         
168         if (op->u.prox->exclusion)
169         {
170             if (*op->u.prox->exclusion)
171                 xmlNewProp(node, BAD_CAST "exclusion", BAD_CAST "true");
172             else
173                 xmlNewProp(node, BAD_CAST "exclusion", BAD_CAST "false");
174         }
175         sprintf(formstr, "%d", *op->u.prox->distance);
176         xmlNewProp(node, BAD_CAST "distance", BAD_CAST formstr);
177
178         if (*op->u.prox->ordered)
179             xmlNewProp(node, BAD_CAST "ordered", BAD_CAST "true");
180         else 
181             xmlNewProp(node, BAD_CAST "ordered", BAD_CAST "false");
182        
183         sprintf(formstr, "%d", *op->u.prox->relationType);
184         xmlNewProp(node, BAD_CAST "relationType", BAD_CAST formstr);
185         
186         switch(op->u.prox->which)
187         {
188         case Z_ProximityOperator_known:
189             sprintf(formstr, "%d", *op->u.prox->u.known);
190             xmlNewProp(node, BAD_CAST "knownProximityUnit",
191                        BAD_CAST formstr);
192             break;
193         default:
194             xmlNewProp(node, BAD_CAST "privateProximityUnit",
195                        BAD_CAST "private");
196             break;
197         }
198     }
199 }
200
201 xmlNodePtr yaz_query2xml_rpnstructure(const Z_RPNStructure *zs,
202                                       xmlNodePtr parent)
203 {
204     if (zs->which == Z_RPNStructure_complex)
205     {
206         Z_Complex *zc = zs->u.complex;
207
208         xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "binary", 0);
209         if (zc->roperator)
210             yaz_query2xml_operator(zc->roperator, node);
211         yaz_query2xml_rpnstructure(zc->s1, node);
212         yaz_query2xml_rpnstructure(zc->s2, node);
213         return node;
214     }
215     else if (zs->which == Z_RPNStructure_simple)
216     {
217         if (zs->u.simple->which == Z_Operand_APT)
218             return yaz_query2xml_apt(zs->u.simple->u.attributesPlusTerm,
219                                      parent);
220         else if (zs->u.simple->which == Z_Operand_resultSetId)
221             return xmlNewChild(parent, /* NS */ 0, BAD_CAST "rset", 
222                                BAD_CAST zs->u.simple->u.resultSetId);
223     }
224     return 0;
225 }
226
227 xmlNodePtr yaz_query2xml_rpn(const Z_RPNQuery *rpn, xmlNodePtr parent)
228 {
229     oident *attrset = oid_getentbyoid (rpn->attributeSetId);
230     if (attrset && attrset->value)
231         xmlNewProp(parent, BAD_CAST "set", BAD_CAST attrset->desc);
232     return yaz_query2xml_rpnstructure(rpn->RPNStructure, parent);
233 }
234
235 xmlNodePtr yaz_query2xml_ccl(const Odr_oct *ccl, xmlNodePtr node)
236 {
237     return 0;
238 }
239
240 xmlNodePtr yaz_query2xml_z3958(const Odr_oct *ccl, xmlNodePtr node)
241 {
242     return 0;
243 }
244
245 xmlNodePtr yaz_query2xml_cql(const char *cql, xmlNodePtr node)
246 {
247     return 0;
248 }
249
250 void yaz_rpnquery2xml(const Z_RPNQuery *rpn, void *docp_void)
251 {
252     Z_Query query;
253
254     query.which = Z_Query_type_1;
255     query.u.type_1 = (Z_RPNQuery *) rpn;
256     yaz_query2xml(&query, docp_void);
257 }
258
259 void yaz_query2xml(const Z_Query *q, void *docp_void)
260 {
261     xmlDocPtr *docp = (xmlDocPtr *) docp_void;
262     xmlNodePtr top_node, child_node = 0;
263     const char *type = 0;
264
265     assert(q);
266     assert(docp);
267
268     top_node = xmlNewNode(0, BAD_CAST "query");
269
270     switch (q->which)
271     {
272     case Z_Query_type_1: 
273     case Z_Query_type_101:
274         type = "rpn";
275         child_node = yaz_query2xml_rpn(q->u.type_1, top_node);
276         break;
277     case Z_Query_type_2:
278         type = "ccl";
279         child_node = yaz_query2xml_ccl(q->u.type_2, top_node);
280         break;
281     case Z_Query_type_100:
282         type = "z39.58";
283         child_node = yaz_query2xml_z3958(q->u.type_100, top_node);
284         break;
285     case Z_Query_type_104:
286         if (q->u.type_104->which == Z_External_CQL)
287         {
288             type = "cql";
289             child_node = yaz_query2xml_cql(q->u.type_104->u.cql, top_node);
290         }
291     }
292     
293     if (child_node && type)
294     {
295         *docp = xmlNewDoc(BAD_CAST "1.0");
296         xmlDocSetRootElement(*docp, top_node); /* make it top node in doc */
297
298         /* set type attribute now */
299         xmlNewProp(top_node, BAD_CAST "type", BAD_CAST type);
300     }
301     else
302     {
303         *docp = 0;
304         xmlFreeNode(top_node);
305     }
306 }
307
308 void yaz_xml2query(const xmlNode node, Z_Query **q, ODR odr)
309 {
310
311
312 }
313
314
315 /* HAVE_XML2 */
316 #endif
317
318 /*
319  * Local variables:
320  * c-basic-offset: 4
321  * indent-tabs-mode: nil
322  * End:
323  * vim: shiftwidth=4 tabstop=8 expandtab
324  */