Remove CQL to Solr conversion and base on cql_transform_t
[yaz-moved-to-github.git] / src / xml_include.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5
6 /** \file
7     \brief XML Include (not to be confused with W3C XInclude)
8 */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <assert.h>
18 #include <yaz/wrbuf.h>
19 #include <yaz/tpath.h>
20 #include <yaz/log.h>
21 #include <yaz/xml_include.h>
22
23 #if YAZ_HAVE_XML2
24
25 #include <libxml/parser.h>
26 #include <libxml/tree.h>
27
28 struct yaz_xml_include_s {
29     const char *confdir;
30     unsigned glob_flags;
31 };
32
33 typedef struct yaz_xml_include_s *yaz_xml_include_t;
34
35 static int process_config_includes(yaz_xml_include_t config, xmlNode *n);
36
37 static void conf_dir_path(yaz_xml_include_t config, WRBUF w, const char *src)
38 {
39     if (config->confdir && *config->confdir > 0 &&
40         !yaz_is_abspath(src))
41     {
42         wrbuf_printf(w, "%s/%s", config->confdir, src);
43     }
44     else
45         wrbuf_puts(w, src);
46 }
47
48 static int config_include_one(yaz_xml_include_t config, xmlNode **sib,
49                               const char *path)
50 {
51     struct stat st;
52     if (stat(path, &st) < 0)
53     {
54         yaz_log(YLOG_FATAL|YLOG_ERRNO, "stat %s", path);
55         return -1;
56     }
57     else
58     {
59         if ((st.st_mode & S_IFMT) == S_IFREG)
60         {
61             xmlDoc *doc = xmlParseFile(path);
62             if (doc)
63             {
64                 xmlNodePtr t = xmlDocGetRootElement(doc);
65                 int ret = process_config_includes(config, t);
66                 *sib = xmlAddNextSibling(*sib, xmlCopyNode(t, 1));
67                 xmlFreeDoc(doc);
68                 if (ret)
69                     return -1;
70             }
71             else
72             {
73                 yaz_log(YLOG_FATAL, "Could not parse %s", path);
74                 return -1;
75             }
76         }
77     }
78     return 0;
79 }
80
81 static int config_include_src(yaz_xml_include_t config, xmlNode **np,
82                               const char *src)
83 {
84     int ret = 0; /* return code. OK so far */
85     WRBUF w = wrbuf_alloc();
86     xmlNodePtr sib; /* our sibling that we append */
87     xmlNodePtr c; /* tmp node */
88
89     wrbuf_printf(w, " begin include src=\"%s\" ", src);
90
91     /* replace include element with a 'begin' comment */
92     sib = xmlNewComment((const xmlChar *) wrbuf_cstr(w));
93     xmlReplaceNode(*np, sib);
94
95     xmlFreeNode(*np);
96
97     wrbuf_rewind(w);
98     conf_dir_path(config, w, src);
99     {
100         int glob_ret;
101         yaz_glob_res_t glob_res;
102
103         glob_ret = yaz_file_glob2(wrbuf_cstr(w), &glob_res, config->glob_flags);
104         if (glob_ret == 0)
105         {
106             size_t i;
107             const char *path;
108             for (i = 0; (path = yaz_file_glob_get_file(glob_res, i)); i++)
109                 ret = config_include_one(config, &sib, path);
110             yaz_file_globfree(&glob_res);
111         }
112     }
113     wrbuf_rewind(w);
114     wrbuf_printf(w, " end include src=\"%s\" ", src);
115     c = xmlNewComment((const xmlChar *) wrbuf_cstr(w));
116     sib = xmlAddNextSibling(sib, c);
117
118     *np = sib;
119     wrbuf_destroy(w);
120     return ret;
121 }
122
123 static int process_config_includes(yaz_xml_include_t config, xmlNode *n)
124 {
125     for (n = n->children; n; n = n->next)
126     {
127         if (n->type == XML_ELEMENT_NODE)
128         {
129             if (!strcmp((const char *) n->name, "include"))
130             {
131                 xmlChar *src = xmlGetProp(n, (xmlChar *) "src");
132                 if (src)
133                 {
134                     int ret = config_include_src(config, &n,
135                                                  (const char *) src);
136                     xmlFree(src);
137                     if (ret)
138                         return ret;
139
140                 }
141             }
142             else
143             {
144                 if (process_config_includes(config, n))
145                     return -1;
146             }
147         }
148     }
149     return 0;
150 }
151
152 int yaz_xml_include_glob(xmlNode *n, const char *base_path,
153                          unsigned glob_flags)
154 {
155     struct yaz_xml_include_s s;
156
157     s.confdir = base_path;
158     s.glob_flags = glob_flags;
159     return process_config_includes(&s, n);
160 }
161
162 int yaz_xml_include_simple(xmlNode *n, const char *base_path)
163 {
164     return yaz_xml_include_glob(n, base_path, 0);
165 }
166
167
168 /* YAZ_HAVE_XML2 */
169 #endif
170
171 /*
172  * Local variables:
173  * c-basic-offset: 4
174  * c-file-style: "Stroustrup"
175  * indent-tabs-mode: nil
176  * End:
177  * vim: shiftwidth=4 tabstop=8 expandtab
178  */
179