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