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