+static int attr_content(struct _xmlAttr *attr, const char *name,
+ const char **dst_content)
+{
+ if (!XML_STRCMP(attr->name, name) && attr->children &&
+ attr->children->type == XML_TEXT_NODE)
+ {
+ *dst_content = (const char *)(attr->children->content);
+ return 1;
+ }
+ return 0;
+}
+
+static void destroy_schemas(struct filter_info *tinfo)
+{
+ struct filter_schema *schema = tinfo->schemas;
+ while (schema)
+ {
+ struct filter_schema *schema_next = schema->next;
+ if (schema->stylesheet_xsp)
+ xsltFreeStylesheet(schema->stylesheet_xsp);
+ xfree(schema);
+ schema = schema_next;
+ }
+ tinfo->schemas = 0;
+ xfree(tinfo->fname);
+ if (tinfo->doc)
+ xmlFreeDoc(tinfo->doc);
+ tinfo->doc = 0;
+}
+
+static ZEBRA_RES create_schemas(struct filter_info *tinfo, const char *fname)
+{
+ xmlNodePtr ptr;
+ tinfo->fname = xstrdup(fname);
+ tinfo->doc = xmlParseFile(tinfo->fname);
+ if (!tinfo->doc)
+ return ZEBRA_FAIL;
+ ptr = xmlDocGetRootElement(tinfo->doc);
+ if (!ptr || ptr->type != XML_ELEMENT_NODE ||
+ XML_STRCMP(ptr->name, "schemaInfo"))
+ return ZEBRA_FAIL;
+ for (ptr = ptr->children; ptr; ptr = ptr->next)
+ {
+ if (ptr->type != XML_ELEMENT_NODE)
+ continue;
+ if (!XML_STRCMP(ptr->name, "schema"))
+ {
+ struct _xmlAttr *attr;
+ struct filter_schema *schema = xmalloc(sizeof(*schema));
+ schema->name = 0;
+ schema->identifier = 0;
+ schema->stylesheet = 0;
+ schema->default_schema = 0;
+ schema->next = tinfo->schemas;
+ schema->stylesheet_xsp = 0;
+ schema->include_snippet = 0;
+ tinfo->schemas = schema;
+ for (attr = ptr->properties; attr; attr = attr->next)
+ {
+ attr_content(attr, "identifier", &schema->identifier);
+ attr_content(attr, "name", &schema->name);
+ attr_content(attr, "stylesheet", &schema->stylesheet);
+ attr_content(attr, "default", &schema->default_schema);
+ attr_content(attr, "snippet", &schema->include_snippet);
+ }
+ if (schema->stylesheet)
+ schema->stylesheet_xsp =
+ xsltParseStylesheetFile(
+ (const xmlChar*) schema->stylesheet);
+ }
+ else if (!XML_STRCMP(ptr->name, "split"))
+ {
+ struct _xmlAttr *attr;
+ for (attr = ptr->properties; attr; attr = attr->next)
+ {
+ attr_content(attr, "level", &tinfo->split_level);
+ attr_content(attr, "path", &tinfo->split_path);
+ }
+ }
+ else
+ {
+ yaz_log(YLOG_WARN, "Bad element %s in %s", ptr->name, fname);
+ return ZEBRA_FAIL;
+ }
+ }
+ return ZEBRA_OK;
+}
+
+static struct filter_schema *lookup_schema(struct filter_info *tinfo,
+ const char *est)
+{
+ struct filter_schema *schema;
+ for (schema = tinfo->schemas; schema; schema = schema->next)
+ {
+ if (est)
+ {
+ if (schema->identifier && !strcmp(schema->identifier, est))
+ return schema;
+ if (schema->name && !strcmp(schema->name, est))
+ return schema;
+ }
+ if (schema->default_schema)
+ return schema;
+ }
+ return 0;
+}
+