2 * Copyright (c) 2002-2003, Index Data.
3 * See the file LICENSE for details.
5 * $Id: srw.c,v 1.4 2003-02-17 22:35:48 adam Exp $
11 #include <libxml/parser.h>
12 #include <libxml/tree.h>
14 static void add_xsd_string_n(xmlNodePtr ptr, const char *elem, char *val,
19 xmlNodePtr c = xmlNewChild(ptr, 0, elem, 0);
20 xmlNodePtr t = xmlNewTextLen(val, len);
25 static void add_xsd_string(xmlNodePtr ptr, const char *elem, char *val)
28 xmlNewChild(ptr, 0, elem, val);
31 static void add_xsd_integer(xmlNodePtr ptr, const char *elem, int *val)
36 sprintf(str, "%d", *val);
37 xmlNewChild(ptr, 0, elem, str);
41 static int match_element(xmlNodePtr ptr, const char *elem)
43 if (ptr->type == XML_ELEMENT_NODE && !strcmp(ptr->name, elem))
48 static int match_xsd_string_n(xmlNodePtr ptr, const char *elem, ODR o,
51 struct _xmlAttr *attr;
52 if (!match_element(ptr, elem))
55 for (attr = ptr->properties; attr; attr = attr->next)
56 if (!strcmp(attr->name, "type") &&
57 attr->children && attr->children->type == XML_TEXT_NODE)
59 const char *t = strchr(attr->children->content, ':');
63 t = attr->children->content;
64 if (!strcmp(t, "string"))
71 if (!ptr || ptr->type != XML_TEXT_NODE)
73 *val = odr_strdup(o, ptr->content);
75 *len = strlen(ptr->content);
80 static int match_xsd_string(xmlNodePtr ptr, const char *elem, ODR o,
83 return match_xsd_string_n(ptr, elem, o, val, 0);
86 static int match_xsd_integer(xmlNodePtr ptr, const char *elem, ODR o, int **val)
88 struct _xmlAttr *attr;
89 if (!match_element(ptr, elem))
92 for (attr = ptr->properties; attr; attr = attr->next)
93 if (!strcmp(attr->name, "type") &&
94 attr->children && attr->children->type == XML_TEXT_NODE)
96 const char *t = strchr(attr->children->content, ':');
100 t = attr->children->content;
101 if (!strcmp(t, "integer"))
108 if (!ptr || ptr->type != XML_TEXT_NODE)
110 *val = odr_intdup(o, atoi(ptr->content));
114 static int yaz_srw_records(ODR o, xmlNodePtr pptr, Z_SRW_record **recs,
115 int *num, void *client_data, const char *ns)
117 if (o->direction == ODR_DECODE)
122 for (ptr = pptr->children; ptr; ptr = ptr->next)
124 if (ptr->type == XML_ELEMENT_NODE &&
125 !strcmp(ptr->name, "record"))
130 *recs = odr_malloc(o, *num * sizeof(**recs));
131 for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next, i++)
133 if (ptr->type == XML_ELEMENT_NODE &&
134 !strcmp(ptr->name, "record"))
137 (*recs)[i].recordSchema = 0;
138 (*recs)[i].recordData_buf = 0;
139 (*recs)[i].recordData_len = 0;
140 (*recs)[i].recordPosition = 0;
141 for (rptr = ptr->children; rptr; rptr = rptr->next)
143 if (match_xsd_string(rptr, "recordSchema", o,
144 &(*recs)[i].recordSchema))
146 else if (match_xsd_string_n(rptr, "recordData", o,
147 &(*recs)[i].recordData_buf,
148 &(*recs)[i].recordData_len))
150 else if (match_xsd_integer(rptr, "recordPosition", o,
151 &(*recs)[i].recordPosition))
157 else if (o->direction == ODR_ENCODE)
160 for (i = 0; i < *num; i++)
162 xmlNodePtr rptr = xmlNewChild(pptr, 0, "record", 0);
163 add_xsd_string(rptr, "recordSchema", (*recs)[i].recordSchema);
164 add_xsd_string_n(rptr, "recordData", (*recs)[i].recordData_buf,
165 (*recs)[i].recordData_len);
166 add_xsd_integer(rptr, "recordPosition", (*recs)[i].recordPosition);
172 static int yaz_srw_diagnostics(ODR o, xmlNodePtr pptr, Z_SRW_diagnostic **recs,
173 int *num, void *client_data, const char *ns)
175 if (o->direction == ODR_DECODE)
180 for (ptr = pptr->children; ptr; ptr = ptr->next)
182 if (ptr->type == XML_ELEMENT_NODE &&
183 !strcmp(ptr->name, "diagnostic"))
188 *recs = odr_malloc(o, *num * sizeof(**recs));
189 for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next, i++)
191 if (ptr->type == XML_ELEMENT_NODE &&
192 !strcmp(ptr->name, "diagnostic"))
196 (*recs)[i].details = 0;
197 for (rptr = ptr->children; rptr; rptr = rptr->next)
199 if (match_xsd_integer(rptr, "code", o,
202 else if (match_xsd_string(rptr, "details", o,
203 &(*recs)[i].details))
210 else if (o->direction == ODR_ENCODE)
213 for (i = 0; i < *num; i++)
215 xmlNodePtr rptr = xmlNewChild(pptr, 0, "diagnostic", 0);
216 add_xsd_integer(rptr, "code", (*recs)[i].code);
217 add_xsd_string(rptr, "details", (*recs)[i].details);
224 int yaz_srw_codec(ODR o, void * vptr, Z_SRW_searchRetrieve **handler_data,
225 void *client_data, const char *ns)
227 xmlNodePtr pptr = vptr;
228 if (o->direction == ODR_DECODE)
230 xmlNodePtr method = pptr->children;
232 while (method && method->type == XML_TEXT_NODE)
233 method = method->next;
235 if (method->type != XML_ELEMENT_NODE)
237 if (method && !strcmp(method->name, "searchRetrieveRequest"))
239 Z_SRW_searchRetrieve **p = handler_data;
240 xmlNodePtr ptr = method->children;
241 Z_SRW_searchRetrieveRequest *req;
243 *p = odr_malloc(o, sizeof(**p));
244 (*p)->which = Z_SRW_searchRetrieve_request;
245 req = (*p)->u.request = odr_malloc(o, sizeof(*req));
250 req->startRecord = 0;
251 req->maximumRecords = 0;
252 req->recordSchema = 0;
253 req->recordPacking = 0;
256 for (; ptr; ptr = ptr->next)
258 if (match_xsd_string(ptr, "query", o,
261 else if (match_xsd_string(ptr, "pQuery", o,
264 else if (match_xsd_string(ptr, "sortKeys", o,
267 else if (match_xsd_string(ptr, "recordSchema", o,
270 else if (match_xsd_string(ptr, "recordPacking", o,
271 &req->recordPacking))
273 else if (match_xsd_integer(ptr, "startRecord", o,
276 else if (match_xsd_integer(ptr, "maximumRecords", o,
277 &req->maximumRecords))
279 else if (match_xsd_string(ptr, "database", o,
282 /* missing is xQuery, xSortKeys .. */
285 else if (method && !strcmp(method->name, "searchRetrieveResponse"))
287 Z_SRW_searchRetrieve **p = handler_data;
288 xmlNodePtr ptr = method->children;
289 Z_SRW_searchRetrieveResponse *res;
291 *p = odr_malloc(o, sizeof(**p));
292 (*p)->which = Z_SRW_searchRetrieve_response;
293 res = (*p)->u.response = odr_malloc(o, sizeof(*res));
295 res->numberOfRecords = 0;
296 res->resultSetId = 0;
297 res->resultSetIdleTime = 0;
299 res->num_records = 0;
300 res->diagnostics = 0;
301 res->num_diagnostics = 0;
302 res->nextRecordPosition = 0;
304 for (; ptr; ptr = ptr->next)
306 if (match_xsd_integer(ptr, "numberOfRecords", o,
307 &res->numberOfRecords))
309 else if (match_xsd_string(ptr, "resultSetId", o,
312 else if (match_xsd_integer(ptr, "resultSetIdleTime", o,
313 &res->resultSetIdleTime))
315 else if (match_element(ptr, "records"))
316 yaz_srw_records(o, ptr, &res->records,
317 &res->num_records, client_data,
319 else if (match_element(ptr, "diagnostics"))
320 yaz_srw_diagnostics(o, ptr, &res->diagnostics,
321 &res->num_diagnostics,
323 else if (match_xsd_integer(ptr, "nextRecordPosition", o,
324 &res->nextRecordPosition))
333 else if (o->direction == ODR_ENCODE)
335 Z_SRW_searchRetrieve **p = handler_data;
336 if ((*p)->which == Z_SRW_searchRetrieve_request)
338 Z_SRW_searchRetrieveRequest *req = (*p)->u.request;
339 xmlNsPtr ns_srw = xmlNewNs(pptr, ns, "zs");
340 xmlNodePtr ptr = xmlNewChild(pptr, ns_srw,
341 "searchRetrieveRequest", 0);
343 add_xsd_string(ptr, "query", req->query);
344 add_xsd_string(ptr, "pQuery", req->pQuery);
345 add_xsd_string(ptr, "sortKeys", req->sortKeys);
346 add_xsd_integer(ptr, "startRecord", req->startRecord);
347 add_xsd_integer(ptr, "maximumRecords", req->maximumRecords);
348 add_xsd_string(ptr, "recordSchema", req->recordSchema);
349 add_xsd_string(ptr, "recordPacking", req->recordPacking);
350 add_xsd_string(ptr, "database", req->database);
352 else if ((*p)->which == Z_SRW_searchRetrieve_response)
354 Z_SRW_searchRetrieveResponse *res = (*p)->u.response;
355 xmlNsPtr ns_srw = xmlNewNs(pptr, ns, "zs");
356 xmlNodePtr ptr = xmlNewChild(pptr, ns_srw,
357 "searchRetrieveResponse", 0);
359 add_xsd_integer(ptr, "numberOfRecords", res->numberOfRecords);
360 add_xsd_string(ptr, "resultSetId", res->resultSetId);
361 add_xsd_integer(ptr, "resultSetIdleTime", res->resultSetIdleTime);
362 if (res->num_records)
364 xmlNodePtr rptr = xmlNewChild(ptr, 0, "records", 0);
365 yaz_srw_records(o, rptr, &res->records, &res->num_records,
368 if (res->num_diagnostics)
370 xmlNodePtr rptr = xmlNewChild(ptr, 0, "diagnostics", 0);
371 yaz_srw_diagnostics(o, rptr, &res->diagnostics,
372 &res->num_diagnostics, client_data, ns);
374 add_xsd_integer(ptr, "nextRecordPosition", res->nextRecordPosition);
383 Z_SRW_searchRetrieve *yaz_srw_get(ODR o, int which)
385 Z_SRW_searchRetrieve *sr = odr_malloc(o, sizeof(*o));
389 case Z_SRW_searchRetrieve_request:
390 sr->u.request = odr_malloc(o, sizeof(*sr->u.request));
391 sr->u.request->query = 0;
392 sr->u.request->xQuery = 0;
393 sr->u.request->pQuery = 0;
394 sr->u.request->sortKeys = 0;
395 sr->u.request->xSortKeys = 0;
396 sr->u.request->startRecord = 0;
397 sr->u.request->maximumRecords = 0;
398 sr->u.request->recordSchema = 0;
399 sr->u.request->recordPacking = 0;
400 sr->u.request->database = 0;
402 case Z_SRW_searchRetrieve_response:
403 sr->u.response = odr_malloc(o, sizeof(*sr->u.response));
404 sr->u.response->numberOfRecords = 0;
405 sr->u.response->resultSetId = 0;
406 sr->u.response->resultSetIdleTime = 0;
407 sr->u.response->records = 0;
408 sr->u.response->num_records = 0;
409 sr->u.response->diagnostics = 0;
410 sr->u.response->num_diagnostics = 0;
411 sr->u.response->nextRecordPosition = 0;
419 const char *yaz_srw_error_str (int code)
426 1 Permanent system error
427 2 System temporarily unavailable
428 3 Authentication error
429 /* Diagnostics Relating to CQL */
432 11 Unsupported query type (XCQL vs CQL)
433 12 Too many characters in query
434 13 Unbalanced or illegal use of parentheses
435 14 Unbalanced or illegal use of quotes
436 15 Illegal or unsupported index set
437 16 Illegal or unsupported index
438 17 Illegal or unsupported combination of index and index set
439 18 Illegal or unsupported combination of indexes
440 19 Illegal or unsupported relation
441 20 Illegal or unsupported relation modifier
442 21 Illegal or unsupported combination of relation modifers
443 22 Illegal or unsupported combination of relation and index
444 23 Too many characters in term
445 24 Illegal combination of relation and term
446 25 Special characters not quoted in term
447 26 Non special character escaped in term
448 27 Empty term unsupported
449 28 Masking character not supported
450 29 Masked words too short
451 30 Too many masking characters in term
452 31 Anchoring character not supported
453 32 Anchoring character in illegal or unsupported position
454 33 Combination of proximity/adjacency and masking characters not supported
455 34 Combination of proximity/adjacency and anchoring characters not supported
456 35 Terms only exclusion (stop) words
457 36 Term in invalid format for index or relation
458 37 Illegal or unsupported boolean operator
459 38 Too many boolean operators in query
460 39 Proximity not supported
461 40 Illegal or unsupported proximity relation
462 41 Illegal or unsupported proximity distance
463 42 Illegal or unsupported proximity unit
464 43 Illegal or unsupported proximity ordering
465 44 Illegal or unsupported combination of proximity modifiers
466 45 Index set name (prefix) assigned to multiple identifiers
467 /* Diagnostics Relating to Result Sets */
469 50 Result sets not supported
470 51 Result set does not exist
471 52 Result set temporarily unavailable
472 53 Result sets only supported for retrieval
473 54 Retrieval may only occur from an existing result set
474 55 Combination of result sets with search terms not supported
475 56 Only combination of single result set with search terms supported
476 57 Result set created but no records available
477 58 Result set created with unpredictable partial results available
478 59 Result set created with valid partial results available
479 /* Diagnostics Relating to Records */
481 60 Too many records retrieved
482 61 First record position out of range
483 62 Negative number of records requested
484 63 System error in retrieving records
485 64 Record temporarily unavailable
486 65 Record does not exist
487 66 Unknown schema for retrieval
488 67 Record not available in this schema
489 68 Not authorised to send record
490 69 Not authorised to send record in this schema
491 70 Record too large to send
492 /* Diagnostics Relating to Sorting */
494 80 Sort not supported
495 81 Unsupported sort type (sortKeys vs xSortKeys)
496 82 Illegal or unsupported sort sequence
498 84 Too many sort keys
499 85 Duplicate sort keys
500 86 Incompatible record formats
501 87 Unsupported schema for sort
502 88 Unsupported tag path for sort
503 89 Tag path illegal or unsupported for schema
504 90 Illegal or unsupported direction value
505 91 Illegal or unsupported case value
506 92 Illegal or unsupported missing value action
507 /* Diagnostics Relating to Explain */
509 100 Explain not supported
510 101 Explain request type not supported (SOAP vs GET)
511 102 Explain record temporarily unavailable