YAZ  4.2.57
xmlquery.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2013 Index Data
3  * See the file LICENSE for details.
4  */
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/oid_db.h>
24 
25 static int check_diagnostic(const xmlNode *ptr, ODR odr,
26  int *error_code, const char **addinfo)
27 {
28  if (ptr && ptr->type == XML_ELEMENT_NODE &&
29  !xmlStrcmp(ptr->name, BAD_CAST "diagnostic"))
30  {
31  struct _xmlAttr *attr;
32  const char *code_str = 0;
33  const char *addinfo_str = 0;
34  for (attr = ptr->properties; attr; attr = attr->next)
35  {
36  if (!xmlStrcmp(attr->name, BAD_CAST "code") &&
37  attr->children && attr->children->type == XML_TEXT_NODE)
38  code_str = (const char *) attr->children->content;
39  else if (!xmlStrcmp(attr->name, BAD_CAST "addinfo") &&
40  attr->children && attr->children->type == XML_TEXT_NODE)
41  addinfo_str = (const char *) attr->children->content;
42  else
43  {
44  *error_code = 1;
45  *addinfo = "bad attribute for diagnostic element";
46  return 1;
47  }
48  }
49  if (!code_str)
50  {
51  *error_code = 1;
52  *addinfo = "missing @code for diagnostic element";
53  return 1;
54  }
55  *error_code = atoi(code_str);
56  if (addinfo_str)
57  *addinfo = odr_strdup(odr, addinfo_str);
58  return 1;
59  }
60  else
61  return 0;
62 }
63 
65  xmlNodePtr parent)
66 {
67  char formstr[30];
68  const char *setname = 0;
69  char oid_name_str[OID_STR_MAX];
70 
71  if (element->attributeSet)
72  {
73  setname = yaz_oid_to_string_buf(element->attributeSet,
74  0, oid_name_str);
75  }
76 
77  if (element->which == Z_AttributeValue_numeric)
78  {
79  xmlNodePtr node = xmlNewChild(parent, 0, BAD_CAST "attr", 0);
80 
81  if (setname)
82  xmlNewProp(node, BAD_CAST "set", BAD_CAST setname);
83 
84  assert(*element->attributeType > 0 && *element->attributeType < 20);
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 ==
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 ==
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 
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;
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;
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 
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++)
177  yaz_query2xml_term(zapt->term, node);
178 
179  return node;
180 }
181 
182 
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  {
230  sprintf(formstr, ODR_INT_PRINTF, *op->u.prox->u.known);
231  xmlNewProp(node, BAD_CAST "knownProximityUnit",
232  BAD_CAST formstr);
233  break;
235  default:
236  xmlNewProp(node, BAD_CAST "privateProximityUnit",
237  BAD_CAST "private");
238  break;
239  }
240  }
241 }
242 
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)
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)
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 
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 
282 static xmlNodePtr yaz_query2xml_ccl(const Odr_oct *ccl, xmlNodePtr node)
283 {
284  return 0;
285 }
286 
287 static xmlNodePtr yaz_query2xml_z3958(const Odr_oct *ccl, xmlNodePtr node)
288 {
289  return 0;
290 }
291 
292 static xmlNodePtr yaz_query2xml_cql(const char *cql, xmlNodePtr node)
293 {
294  return 0;
295 }
296 
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 
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 
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 
356 static Odr_int *intVal(ODR odr, const char *str)
357 {
358  return odr_intdup(odr, atoi(str));
359 }
360 
361 static void yaz_xml2query_operator(const xmlNode *ptr, Z_Operator **op,
362  ODR odr,
363  int *error_code, const char **addinfo)
364 {
365  xmlChar *type = xmlGetProp((xmlNodePtr) ptr, BAD_CAST "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 (!xmlStrcmp(type, BAD_CAST "and"))
374  {
375  (*op)->which = Z_Operator_and;
376  (*op)->u.op_and = odr_nullval();
377  }
378  else if (!xmlStrcmp(type, BAD_CAST "or"))
379  {
380  (*op)->which = Z_Operator_or;
381  (*op)->u.op_or = odr_nullval();
382  }
383  else if (!xmlStrcmp(type, BAD_CAST "not"))
384  {
385  (*op)->which = Z_Operator_and_not;
386  (*op)->u.and_not = odr_nullval();
387  }
388  else if (!xmlStrcmp(type, BAD_CAST "prox"))
389  {
390  struct _xmlAttr *attr;
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 =
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  {
420  pop->u.known = intVal(odr, value);
421  }
422  else if (!xmlStrcmp(attr->name, BAD_CAST "privateProximityUnit"))
423  {
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  xmlFree(type);
441 }
442 
443 static void yaz_xml2query_attribute_element(const xmlNode *ptr,
444  Z_AttributeElement **elem, ODR odr,
445  int *error_code,
446  const char **addinfo)
447 {
448  int i;
449  xmlChar *set = 0;
450  xmlChar *type = 0;
451  xmlChar *value = 0;
452  int num_values = 0;
453  struct _xmlAttr *attr;
454  for (attr = ptr->properties; attr; attr = attr->next)
455  {
456  if (!xmlStrcmp(attr->name, BAD_CAST "set") &&
457  attr->children && attr->children->type == XML_TEXT_NODE)
458  set = attr->children->content;
459  else if (!xmlStrcmp(attr->name, BAD_CAST "type") &&
460  attr->children && attr->children->type == XML_TEXT_NODE)
461  type = attr->children->content;
462  else if (!xmlStrcmp(attr->name, BAD_CAST "value") &&
463  attr->children && attr->children->type == XML_TEXT_NODE)
464  {
465  value = attr->children->content;
466  num_values++;
467  }
468  else
469  {
470  *error_code = 1;
471  *addinfo = "bad attribute for attr content";
472  return;
473  }
474  }
475  if (!type)
476  {
477  *error_code = 1;
478  *addinfo = "missing type attribute for att content";
479  return;
480  }
481  if (!value)
482  {
483  *error_code = 1;
484  *addinfo = "missing value attribute for att content";
485  return;
486  }
487 
488  *elem = (Z_AttributeElement *) odr_malloc(odr, sizeof(**elem));
489  if (set)
490  (*elem)->attributeSet = yaz_string_to_oid_odr(yaz_oid_std(),
491  CLASS_ATTSET,
492  (const char *) set,
493  odr);
494  else
495  (*elem)->attributeSet = 0;
496  (*elem)->attributeType = intVal(odr, (const char *) type);
497 
498  /* looks like a number ? */
499  for (i = 0; value[i] && value[i] >= '0' && value[i] <= '9'; i++)
500  ;
501  if (num_values > 1 || value[i])
502  { /* multiple values or string, so turn to complex attribute */
503  (*elem)->which = Z_AttributeValue_complex;
504  (*elem)->value.complex =
506  (*elem)->value.complex->num_list = num_values;
507  (*elem)->value.complex->list = (Z_StringOrNumeric **)
508  odr_malloc(odr, sizeof(Z_StringOrNumeric*) * num_values);
509 
510  /* second pass over attr values */
511  i = 0;
512  for (attr = ptr->properties; attr; attr = attr->next)
513  {
514  if (!xmlStrcmp(attr->name, BAD_CAST "value") &&
515  attr->children && attr->children->type == XML_TEXT_NODE)
516  {
517  const char *val = (const char *) attr->children->content;
518  assert (i < num_values);
519  (*elem)->value.complex->list[i] = (Z_StringOrNumeric *)
520  odr_malloc(odr, sizeof(Z_StringOrNumeric));
521  (*elem)->value.complex->list[i]->which =
523  (*elem)->value.complex->list[i]->u.string =
524  odr_strdup(odr, val);
525  i++;
526  }
527  }
528  (*elem)->value.complex->num_semanticAction = 0;
529  (*elem)->value.complex->semanticAction = 0;
530  }
531  else
532  { /* good'ld numeric value */
533  (*elem)->which = Z_AttributeValue_numeric;
534  (*elem)->value.numeric = intVal(odr, (const char *) value);
535  }
536 }
537 
538 static char *strVal(const xmlNode *ptr_cdata, ODR odr)
539 {
540  return nmem_text_node_cdata(ptr_cdata, odr_getmem(odr));
541 }
542 
543 static void yaz_xml2query_term(const xmlNode *ptr, Z_Term **term, ODR odr,
544  int *error_code, const char **addinfo)
545 {
546  xmlChar *type = 0;
547  struct _xmlAttr *attr;
548  char *cdata = strVal(ptr->children, odr);
549 
550  for (attr = ptr->properties; attr; attr = attr->next)
551  {
552  if (!xmlStrcmp(attr->name, BAD_CAST "type") &&
553  attr->children && attr->children->type == XML_TEXT_NODE)
554  type = attr->children->content;
555  else
556  {
557  *error_code = 1;
558  *addinfo = "bad attribute for attr content";
559  return;
560  }
561  }
562  *term = (Z_Term *) odr_malloc(odr, sizeof(Z_Term));
563 
564  if (!type || !xmlStrcmp(type, BAD_CAST "general"))
565  {
566  (*term)->which = Z_Term_general;
567  (*term)->u.general =
568  odr_create_Odr_oct(odr, (unsigned char *)cdata, strlen(cdata));
569  }
570  else if (!xmlStrcmp(type, BAD_CAST "numeric"))
571  {
572  (*term)->which = Z_Term_numeric;
573  (*term)->u.numeric = intVal(odr, cdata);
574  }
575  else if (!xmlStrcmp(type, BAD_CAST "string"))
576  {
577  (*term)->which = Z_Term_characterString;
578  (*term)->u.characterString = cdata;
579  }
580  else if (!xmlStrcmp(type, BAD_CAST "oid"))
581  {
582  *error_code = 1;
583  *addinfo = "unhandled term type: oid";
584  }
585  else if (!xmlStrcmp(type, BAD_CAST "dateTime"))
586  {
587  *error_code = 1;
588  *addinfo = "unhandled term type: dateTime";
589  }
590  else if (!xmlStrcmp(type, BAD_CAST "integerAndUnit"))
591  {
592  *error_code = 1;
593  *addinfo = "unhandled term type: integerAndUnit";
594  }
595  else if (!xmlStrcmp(type, BAD_CAST "null"))
596  {
597  (*term)->which = Z_Term_null;
598  (*term)->u.null = odr_nullval();
599  }
600  else
601  {
602  *error_code = 1;
603  *addinfo = "unhandled term type";
604  }
605 }
606 
607 static void yaz_xml2query_apt(const xmlNode *ptr_apt,
608  Z_AttributesPlusTerm **zapt, ODR odr,
609  int *error_code, const char **addinfo)
610 {
611  const xmlNode *ptr = ptr_apt->children;
612  int i, num_attr = 0;
613 
614  *zapt = (Z_AttributesPlusTerm *)
615  odr_malloc(odr, sizeof(Z_AttributesPlusTerm));
616 
617  /* deal with attributes */
618  (*zapt)->attributes = (Z_AttributeList*)
619  odr_malloc(odr, sizeof(Z_AttributeList));
620 
621  /* how many attributes? */
622  for (; ptr; ptr = ptr->next)
623  if (ptr->type == XML_ELEMENT_NODE)
624  {
625  if (!xmlStrcmp(ptr->name, BAD_CAST "attr"))
626  num_attr++;
627  else
628  break;
629  }
630 
631  /* allocate and parse for real */
632  (*zapt)->attributes->num_attributes = num_attr;
633  (*zapt)->attributes->attributes = (Z_AttributeElement **)
634  odr_malloc(odr, sizeof(Z_AttributeElement*) * num_attr);
635 
636  i = 0;
637  ptr = ptr_apt->children;
638  for (; ptr; ptr = ptr->next)
639  if (ptr->type == XML_ELEMENT_NODE)
640  {
641  if (!xmlStrcmp(ptr->name, BAD_CAST "attr"))
642  {
644  ptr, &(*zapt)->attributes->attributes[i], odr,
645  error_code, addinfo);
646  i++;
647  }
648  else
649  break;
650  }
651  if (check_diagnostic(ptr, odr, error_code, addinfo))
652  return;
653 
654  if (ptr && ptr->type == XML_ELEMENT_NODE)
655  {
656  if (!xmlStrcmp(ptr->name, BAD_CAST "term"))
657  {
658  /* deal with term */
659  yaz_xml2query_term(ptr, &(*zapt)->term, odr, error_code, addinfo);
660  }
661  else
662  {
663  *error_code = 1;
664  *addinfo = "bad element in apt content";
665  }
666  }
667  else
668  {
669  *error_code = 1;
670  *addinfo = "missing term node in apt content";
671  }
672 }
673 
674 static void yaz_xml2query_rset(const xmlNode *ptr, Z_ResultSetId **rset,
675  ODR odr, int *error_code, const char **addinfo)
676 {
677  if (ptr->children)
678  {
679  *rset = strVal(ptr->children, odr);
680  }
681  else
682  {
683  *error_code = 1;
684  *addinfo = "missing rset content";
685  }
686 }
687 
688 static void yaz_xml2query_rpnstructure(const xmlNode *ptr, Z_RPNStructure **zs,
689  ODR odr,
690  int *error_code, const char **addinfo)
691 {
692  while (ptr && ptr->type != XML_ELEMENT_NODE)
693  ptr = ptr->next;
694 
695  if (!ptr || ptr->type != XML_ELEMENT_NODE)
696  {
697  *error_code = 1;
698  *addinfo = "missing rpn operator, rset, apt node";
699  return;
700  }
701  if (check_diagnostic(ptr, odr, error_code, addinfo))
702  return;
703 
704  *zs = (Z_RPNStructure *) odr_malloc(odr, sizeof(Z_RPNStructure));
705  if (!xmlStrcmp(ptr->name, BAD_CAST "operator"))
706  {
707  Z_Complex *zc = (Z_Complex *) odr_malloc(odr, sizeof(Z_Complex));
708 
709  (*zs)->which = Z_RPNStructure_complex;
710  (*zs)->u.complex = zc;
711 
712  yaz_xml2query_operator(ptr, &zc->roperator, odr, error_code, addinfo);
713 
714  ptr = ptr->children;
715  while (ptr && ptr->type != XML_ELEMENT_NODE)
716  ptr = ptr->next;
717  yaz_xml2query_rpnstructure(ptr, &zc->s1, odr, error_code, addinfo);
718  if (ptr)
719  ptr = ptr->next;
720  while (ptr && ptr->type != XML_ELEMENT_NODE)
721  ptr = ptr->next;
722  yaz_xml2query_rpnstructure(ptr, &zc->s2, odr, error_code, addinfo);
723  }
724  else
725  {
726  Z_Operand *s = (Z_Operand *) odr_malloc(odr, sizeof(Z_Operand));
727  (*zs)->which = Z_RPNStructure_simple;
728  (*zs)->u.simple = s;
729  if (!xmlStrcmp(ptr->name, BAD_CAST "apt"))
730  {
731  s->which = Z_Operand_APT;
733  odr, error_code, addinfo);
734  }
735  else if (!xmlStrcmp(ptr->name, BAD_CAST "rset"))
736  {
739  odr, error_code, addinfo);
740  }
741  else
742  {
743  *error_code = 1;
744  *addinfo = "bad element: expected binary, apt or rset";
745  }
746  }
747 }
748 
749 static void yaz_xml2query_rpn(const xmlNode *ptr, Z_RPNQuery **query, ODR odr,
750  int *error_code, const char **addinfo)
751 {
752  xmlChar *set = xmlGetProp((xmlNodePtr) ptr, BAD_CAST "set");
753 
754  *query = (Z_RPNQuery*) odr_malloc(odr, sizeof(Z_RPNQuery));
755  if (set)
756  {
757  (*query)->attributeSetId =
759  CLASS_ATTSET, (const char *) set, odr);
760  xmlFree(set);
761  }
762  else
763  (*query)->attributeSetId = 0;
764  yaz_xml2query_rpnstructure(ptr->children, &(*query)->RPNStructure,
765  odr, error_code, addinfo);
766 }
767 
768 static void yaz_xml2query_(const xmlNode *ptr, Z_Query **query, ODR odr,
769  int *error_code, const char **addinfo)
770 {
771  if (check_diagnostic(ptr, odr, error_code, addinfo))
772  return;
773  if (ptr && ptr->type == XML_ELEMENT_NODE &&
774  !xmlStrcmp(ptr->name, BAD_CAST "query"))
775  {
776  const char *type;
777  ptr = ptr->children;
778  while (ptr && ptr->type != XML_ELEMENT_NODE)
779  ptr = ptr->next;
780  if (!ptr || ptr->type != XML_ELEMENT_NODE)
781  {
782  *error_code = 1;
783  *addinfo = "missing query content";
784  return;
785  }
786  type = (const char *) ptr->name;
787 
788  *query = (Z_Query*) odr_malloc(odr, sizeof(Z_Query));
789  if (!type || !strcmp(type, "rpn"))
790  {
791  (*query)->which = Z_Query_type_1;
792  yaz_xml2query_rpn(ptr, &(*query)->u.type_1, odr,
793  error_code, addinfo);
794  }
795  else if (!strcmp(type, "ccl"))
796  {
797  *error_code = 1;
798  *addinfo = "ccl not supported yet";
799  }
800  else if (!strcmp(type, "z39.58"))
801  {
802  *error_code = 1;
803  *addinfo = "z39.58 not supported yet";
804  }
805  else if (!strcmp(type, "cql"))
806  {
807  *error_code = 1;
808  *addinfo = "cql not supported yet";
809  }
810  else
811  {
812  *error_code = 1;
813  *addinfo = "unsupported query type";
814  }
815  }
816  else
817  {
818  *error_code = 1;
819  *addinfo = "missing query element";
820  }
821 }
822 
823 void yaz_xml2query(const xmlNode *xmlnodep, Z_Query **query, ODR odr,
824  int *error_code, const char **addinfo)
825 {
826  yaz_xml2query_(xmlnodep, query, odr, error_code, addinfo);
827 }
828 
829 /* YAZ_HAVE_XML2 */
830 #endif
831 
832 /*
833  * Local variables:
834  * c-basic-offset: 4
835  * c-file-style: "Stroustrup"
836  * indent-tabs-mode: nil
837  * End:
838  * vim: shiftwidth=4 tabstop=8 expandtab
839  */
840