]> git.mxchange.org Git - flightgear.git/blob - utils/xmlgrep/xmlgrep.c
5f8e92cd0ece948466c3d3f43bf7c92d103256b7
[flightgear.git] / utils / xmlgrep / xmlgrep.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "xml.h"
6
7 static const char *_static_root = "/";
8 static unsigned int _fcount = 0;
9 static char **_filenames = 0;
10 static char *_element = 0;
11 static char *_value = 0;
12 static char *_root = 0;
13 static char *_print = 0;
14 static int print_filenames = 0;
15
16 static void free_and_exit(int i);
17
18 #define SHOW_NOVAL(opt) \
19 { \
20     printf("option '%s' requires a value\n\n", (opt)); \
21     free_and_exit(-1); \
22 }
23
24 void
25 show_help ()
26 {
27     printf("usage: xmlgrep [options] [file ...]\n\n");
28     printf("Options:\n");
29     printf("\t-h\t\tshow this help message\n");
30     printf("\t-e <id>\t\tshow sections that contain this element\n");
31     printf("\t-p <id>\t\tprint this element as the output\n");
32     printf("\t-r <path>\tspecify the XML search root\n");
33     printf("\t-v <string>\tshow sections where one of the elements has this ");
34     printf("value\n\n");
35     printf(" To print the contents of the 'type' element of the XML section ");
36     printf("that begins\n at '/printer/output' one would use the following ");
37     printf("syntax:\n\n\txmlgrep -r /printer/output -p type sample.xml\n\n");
38     printf(" To filter out sections that contain the 'driver' element with ");
39     printf("'generic' as\n it's value one would issue the following command:");
40     printf("\n\n\txmlgrep -r /printer/output -e driver -v generic sample.xml");
41     printf("\n\n");
42     free_and_exit(0);
43 }
44
45 void
46 free_and_exit(int i)
47 {
48     if (_root != _static_root) free(_root);
49     if (_element) free(_element);
50     if (_value) free(_value);
51     if (_print) free(_print);
52     if (_filenames)
53     {
54         for (i=0; i < _fcount; i++)
55         {
56             if (_filenames[i])
57             {
58                 if (print_filenames) printf("%s\n", _filenames[i]);
59                 free(_filenames[i]);
60             }
61         }
62         free(_filenames);
63     }
64  
65     exit(i);
66 }
67
68 int
69 parse_option(char **args, int n, int max)
70 {
71     char *opt, *arg = 0;
72     int sz;
73
74     opt = args[n];
75     if (opt[0] == '-' && opt[1] == '-')
76         opt++;
77
78     if ((arg = strchr(opt, '=')) != NULL)
79     {
80         *arg++ = 0;
81     }
82     else if (++n < max)
83     {
84         arg = args[n];
85 #if 0
86         if (arg && arg[0] == '-')
87             arg = 0;
88 #endif
89     }
90
91     sz = strlen(opt);
92     if (strncmp(opt, "-help", sz) == 0)
93     {
94         show_help();
95     }
96     else if (strncmp(opt, "-root", sz) == 0)
97     {
98         if (arg == 0) SHOW_NOVAL(opt);
99         _root = strdup(arg);
100         return 2;
101     }
102     else if (strncmp(opt, "-element", sz) == 0)
103     {
104         if (arg == 0) SHOW_NOVAL(opt);
105         _element = strdup(arg);
106         return 2;
107     }
108     else if (strncmp(opt, "-value", sz) == 0)
109     {
110         if (arg == 0) SHOW_NOVAL(opt);
111         _value = strdup(arg);
112         return 2;
113     }
114     else if (strncmp(opt, "-print", sz) == 0)
115     {
116         if (arg == 0) SHOW_NOVAL(opt);
117         _print = strdup(arg);
118         return 2;
119     }
120     else if (strncmp(opt, "-list-filenames", sz) == 0)
121     { /* undocumented test argument */
122         print_filenames = 1;
123         return 1;
124     }
125     else if (opt[0] == '-')
126     {
127         printf("Unknown option %s\n", opt);
128         free_and_exit(-1);
129     }
130     else
131     {
132         int pos = _fcount++;
133         if (_filenames == 0)
134         {
135             _filenames = (char **)malloc(sizeof(char*));
136         }
137         else
138         {
139             char **ptr = (char **)realloc(_filenames, _fcount*sizeof(char*));
140             if (ptr == 0)
141             {
142                 printf("Out of memory.\n\n");
143                 free_and_exit(-1);
144             }
145            _filenames = ptr;
146         }
147
148         _filenames[pos] = strdup(opt);
149     }
150
151     return 1;
152 }
153
154 void walk_the_tree(size_t num, void *xid, char *tree)
155 {
156     unsigned int q, no_elements;
157     char *elem, *next;
158
159     elem = tree;
160     if (*elem == '/') elem++;
161
162     next = strchr(elem, '/');
163     if (!next)                                  /* last node from the tree */
164     {
165         void *elem_id = xmlMarkId(xid);
166
167         no_elements = xmlGetNumElements(xid, elem);
168         for (q=0; q<no_elements; q++)
169         {
170             void *node_id = xmlGetNextElement(xid, elem_id, elem);
171             if (node_id && _print)
172             {
173                 unsigned int i, no_nodes;
174                 void *xmid;
175
176                 xmid = xmlMarkId(node_id);
177
178                 no_nodes = xmlGetNumElements(node_id, _print);
179                 for (i=0; i<no_nodes; i++)
180                 {
181                     if (xmlGetNextElement(node_id, xmid, _print) != 0)
182                     {
183                         char *value = xmlGetString(xmid);
184                         if (value)
185                         {
186                             printf("%s: <%s>%s</%s>\n",
187                                    _filenames[num], _print, value, _print);
188                             free(value);
189                         }
190                     }
191                 }
192                 free(xmid);
193             }
194             else if (node_id && _value)
195             {
196                 if (_element)
197                 {
198                     unsigned int i, no_nodes;
199                     void *xmid;
200
201                     xmid = xmlMarkId(node_id);
202
203                     no_nodes = xmlGetNumElements(node_id, _element);
204                     for (i=0; i<no_nodes; i++)
205                     {
206                         xmlGetNextElement(node_id, xmid, _element);
207                         if (xmlCompareString(xmid, _value) == 0)
208                         {
209                             printf("%s: <%s>%s</%s>\n",
210                                    _filenames[num], _element, _value, _element);
211                         }
212                     }
213                     free(xmid);
214                 }
215                 else
216                 {
217                 }
218             }
219             else if (node_id && _element)
220             {
221             }
222         }
223         free(elem_id);
224     }
225     else                                 /* walk the rest of the tree */
226     {
227         void *xmid;
228
229         xmid = xmlMarkId(xid);
230         if (xmid)
231         {
232             *next++ = 0;
233
234             no_elements = xmlGetNumElements(xid, elem);
235             for (q=0; q<no_elements; q++)
236             {
237                 void *elem_id = xmlGetNextElement(xid, xmid, elem);
238                 walk_the_tree(num, elem_id, next);
239             }
240
241             *--next = '/';
242
243             free(xmid);
244         }
245         else printf("Error executing xmlMarkId\n");
246     }
247 }
248
249
250 void grep_file(unsigned num)
251 {
252     void *xrid;
253
254     xrid = xmlOpen(_filenames[num]);
255     if (xrid)
256     {
257        void *xid = xmlMarkId(xrid);
258        walk_the_tree(num, xrid, _root);
259        free(xrid);
260        xrid = xid;
261     }
262     else
263     {
264         fprintf(stderr, "Error reading file '%s'\n", _filenames[num]);
265     }
266
267     xmlClose(xrid);
268 }
269
270 int
271 main (int argc, char **argv)
272 {
273     int i;
274
275     if (argc == 1)
276         show_help();
277
278     for (i=1; i<argc;)
279     {
280         int ret = parse_option(argv, i, argc);
281         i += ret;
282     }
283
284     if (_root == 0) (_root = (char *)_static_root);
285
286     for (i=0; i<_fcount; i++)
287         grep_file(i);
288
289     free_and_exit(0);
290
291     return 0;
292 }