Added initial implementation for XML Query 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.1 2006-01-27 17:28:16 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 xmlNodePtr yaz_query2xml_attribute_element(const Z_AttributeElement *element,
24                                            xmlNodePtr parent)
25 {
26     xmlNodePtr node = xmlNewChild(parent, 0, BAD_CAST "attr", 0);
27 #if 0
28     int i;
29     char *setname  = 0;
30     if (element->attributeSet)
31     {
32         oident *attrset;
33         attrset = oid_getentbyoid (element->attributeSet);
34         setname = attrset->desc;
35     }
36     switch (element->which) 
37     {
38     case Z_AttributeValue_numeric:
39         wrbuf_printf(b,"@attr %s%s%d=%d ", setname, sep,
40                      *element->attributeType, *element->value.numeric);
41         break;
42     case Z_AttributeValue_complex:
43         wrbuf_printf(b,"@attr %s%s\"%d=", setname, sep,
44                      *element->attributeType);
45         for (i = 0; i<element->value.complex->num_list; i++)
46         {
47             if (i)
48                 wrbuf_printf(b,",");
49             if (element->value.complex->list[i]->which ==
50                 Z_StringOrNumeric_string)
51                 wrbuf_printf (b, "%s",
52                               element->value.complex->list[i]->u.string);
53             else if (element->value.complex->list[i]->which ==
54                      Z_StringOrNumeric_numeric)
55                 wrbuf_printf (b, "%d", 
56                               *element->value.complex->list[i]->u.numeric);
57         }
58         wrbuf_printf(b, "\" ");
59         break;
60     default:
61         wrbuf_printf (b, "@attr 1=unknown ");
62     }
63 #endif
64     return node;
65 }
66
67
68 xmlNodePtr yaz_query2xml_term(const Z_Term *term,
69                               xmlNodePtr parent)
70 {
71     xmlNodePtr t = 0;
72     xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "term", 0);
73     char formstr[20];
74
75     switch (term->which)
76     {
77     case Z_Term_general:
78         t = xmlNewTextLen(BAD_CAST term->u.general->buf, term->u.general->len);
79         break;
80     case Z_Term_characterString:
81         t = xmlNewText(BAD_CAST term->u.characterString);
82         break;
83     case Z_Term_numeric:
84         sprintf(formstr, "%d", *term->u.numeric);
85         t = xmlNewText(BAD_CAST formstr);       
86         break;
87     case Z_Term_null:
88         break;
89     default:
90         break;
91     }
92     if (t) /* got a term node ? */
93         xmlAddChild(node, t);
94     return node;
95 }
96
97 xmlNodePtr yaz_query2xml_apt(const Z_AttributesPlusTerm *zapt,
98                              xmlNodePtr parent)
99 {
100     xmlNodePtr node = xmlNewChild(parent, /* NS */ 0, BAD_CAST "apt", 0);
101     int num_attributes = zapt->attributes->num_attributes;
102     int i;
103     for (i = 0; i<num_attributes; i++)
104         yaz_query2xml_attribute_element(zapt->attributes->attributes[i], node);
105     yaz_query2xml_term(zapt->term, node);
106
107     return node;
108 }
109
110 xmlNodePtr yaz_query2xml_rpnstructure(const Z_RPNStructure *zs,
111                                       xmlNodePtr parent)
112 {
113     if (zs->which == Z_RPNStructure_complex)
114     {
115         return 0;
116 #if 0
117         Z_Operator *op = zs->u.complex->roperator;
118         wrbuf_printf(b, "@%s ", complex_op_name(op) );
119         if (op->which== Z_Operator_prox)
120         {
121             if (!op->u.prox->exclusion)
122                 wrbuf_putc(b, 'n');
123             else if (*op->u.prox->exclusion)
124                 wrbuf_putc(b, '1');
125             else
126                 wrbuf_putc(b, '0');
127
128             wrbuf_printf(b, " %d %d %d ", *op->u.prox->distance,
129                          *op->u.prox->ordered,
130                          *op->u.prox->relationType);
131
132             switch(op->u.prox->which)
133             {
134             case Z_ProximityOperator_known:
135                 wrbuf_putc(b, 'k');
136                 break;
137             case Z_ProximityOperator_private:
138                 wrbuf_putc(b, 'p');
139                 break;
140             default:
141                 wrbuf_printf(b, "%d", op->u.prox->which);
142             }
143             if (op->u.prox->u.known)
144                 wrbuf_printf(b, " %d ", *op->u.prox->u.known);
145             else
146                 wrbuf_printf(b, " 0 ");
147         }
148         yaz_rpnstructure_to_wrbuf(b,zs->u.complex->s1);
149         yaz_rpnstructure_to_wrbuf(b,zs->u.complex->s2);
150 #endif
151     }
152     else if (zs->which == Z_RPNStructure_simple)
153     {
154         if (zs->u.simple->which == Z_Operand_APT)
155             return yaz_query2xml_apt(zs->u.simple->u.attributesPlusTerm,
156                                      parent);
157         else if (zs->u.simple->which == Z_Operand_resultSetId)
158         {
159             return 0;
160 #if 0
161             yaz_term_to_wrbuf(b, zs->u.simple->u.resultSetId,
162                               strlen(zs->u.simple->u.resultSetId));
163 #endif
164         }
165         else
166             return 0;
167     }
168     return 0;
169 }
170
171 xmlNodePtr yaz_query2xml_rpn(const Z_RPNQuery *rpn, xmlNodePtr parent)
172 {
173     oident *attrset = oid_getentbyoid (rpn->attributeSetId);
174     if (attrset && attrset->value)
175         parent = xmlNewChild(parent, /*ns */ 0,
176                              BAD_CAST "attrset", BAD_CAST attrset->desc);
177     return yaz_query2xml_rpnstructure(rpn->RPNStructure, parent);
178 }
179
180 xmlNodePtr yaz_query2xml_ccl(const Odr_oct *ccl, xmlNodePtr node)
181 {
182     return 0;
183 }
184
185 xmlNodePtr yaz_query2xml_z3958(const Odr_oct *ccl, xmlNodePtr node)
186 {
187     return 0;
188 }
189
190 xmlNodePtr yaz_query2xml_cql(const char *cql, xmlNodePtr node)
191 {
192     return 0;
193 }
194
195 void yaz_query2xml(const Z_Query *q, void *docp_void)
196 {
197     xmlDocPtr *docp = (xmlDocPtr *) docp_void;
198     xmlNodePtr top_node, child_node = 0;
199     const char *type = 0;
200
201     assert(q);
202     assert(docp);
203
204     top_node = xmlNewNode(0, BAD_CAST "query");
205
206     switch (q->which)
207     {
208     case Z_Query_type_1: 
209     case Z_Query_type_101:
210         type = "rpn";
211         child_node = yaz_query2xml_rpn(q->u.type_1, top_node);
212         break;
213     case Z_Query_type_2:
214         type = "ccl";
215         child_node = yaz_query2xml_ccl(q->u.type_2, top_node);
216         break;
217     case Z_Query_type_100:
218         type = "z39.58";
219         child_node = yaz_query2xml_z3958(q->u.type_100, top_node);
220         break;
221     case Z_Query_type_104:
222         if (q->u.type_104->which == Z_External_CQL)
223         {
224             type = "cql";
225             child_node = yaz_query2xml_cql(q->u.type_104->u.cql, top_node);
226         }
227     }
228     
229     if (child_node && type)
230     {
231         *docp = xmlNewDoc(BAD_CAST "1.0");
232         xmlDocSetRootElement(*docp, top_node); /* make it top node in doc */
233
234         /* set type attribute now */
235         xmlNewProp(top_node, BAD_CAST "type", BAD_CAST type);
236     }
237     else
238     {
239         *docp = 0;
240         xmlFreeNode(top_node);
241     }
242 }
243
244 void yaz_xml2query(const xmlNode node, Z_Query **q, ODR odr)
245 {
246
247
248 }
249
250
251 /* HAVE_XML2 */
252 #endif
253
254 /*
255  * Local variables:
256  * c-basic-offset: 4
257  * indent-tabs-mode: nil
258  * End:
259  * vim: shiftwidth=4 tabstop=8 expandtab
260  */