9 # define strncasecmp strnicmp
13 #include <unistd.h> /* read */
14 #include <sys/stat.h> /* fstat */
15 #include <fcntl.h> /* open */
19 static const char *_static_root = "/";
20 static const char *_static_element = "*";
21 static unsigned int _fcount = 0;
22 static char **_filenames = 0;
23 static char *_element = 0;
24 static char *_value = 0;
25 static char *_root = 0;
26 static char *_print = 0;
27 static char *_attribute = 0;
28 static int print_filenames = 0;
30 static void free_and_exit(int i);
33 #define NODE_NAME_LEN 256
34 #define STRING_LEN 2048
36 #define SHOW_NOVAL(opt) \
38 printf("option '%s' requires a value\n\n", (opt)); \
45 printf("usage: xmlgrep [options] [file ...]\n\n");
47 printf("\t-h\t\tshow this help message\n");
48 printf("\t-a <string>\tprint this attribute as the output\n");
49 printf("\t-e <id>\t\tshow sections that contain this element\n");
50 printf("\t-p <id>\t\tprint this element as the output\n");
51 printf("\t-r <path>\tspecify the XML search root\n");
52 printf("\t-v <string>\tfilter sections that contain this vale\n\n");
53 printf(" To print the contents of the 'type' element of the XML section ");
54 printf("that begins\n at '/printer/output' use the following command:\n\n");
55 printf("\txmlgrep -r /printer/output -p type sample.xml\n\n");
56 printf(" To filter 'output' elements under '/printer' that have attribute");
57 printf(" 'n' set to '1'\n use the following command:\n\n");
58 printf("\txmlgrep -r /printer -p output -a n -v 1 sample.xml\n\n");
59 printf(" To filter out sections that contain the 'driver' element with ");
60 printf("'generic' as\n it's value use the following command:");
61 printf("\n\n\txmlgrep -r /printer/output -e driver -v generic sample.xml");
67 free_and_exit(int ret)
69 if (_root && _root != _static_root) free(_root);
70 if (_element && _element != _static_element) free(_element);
71 if (_value) free(_value);
72 if (_print) free(_print);
73 if (_attribute) free(_attribute);
77 for (i=0; i < _fcount; i++)
81 if (print_filenames) printf("%s\n", _filenames[i]);
92 parse_option(char **args, int n, int max)
95 unsigned int alen = 0;
99 if (strncmp(opt, "--", 2) == 0)
102 if ((arg = strchr(opt, '=')) != NULL)
110 if (arg && arg[0] == '-')
116 if (strncmp(opt, "-help", olen) == 0)
120 else if (strncmp(opt, "-root", olen) == 0)
122 if (arg == 0) SHOW_NOVAL(opt);
123 alen = strlen(arg)+1;
124 if (_root) free(_root);
125 _root = malloc(alen);
126 memcpy(_root, arg, alen);
129 else if (strncmp(opt, "-element", olen) == 0)
131 if (arg == 0) SHOW_NOVAL(opt);
132 alen = strlen(arg)+1;
133 if (_element) free(_element);
134 _element = malloc(alen);
135 memcpy(_element, arg, alen);
138 else if (strncmp(opt, "-value", olen) == 0)
140 if (arg == 0) SHOW_NOVAL(opt);
141 alen = strlen(arg)+1;
142 if (_value) free(_value);
143 _value = malloc(alen);
144 memcpy(_value, arg, alen);
147 else if (strncmp(opt, "-print", olen) == 0)
149 if (arg == 0) SHOW_NOVAL(opt);
150 alen = strlen(arg)+1;
151 if (_print) free(_print);
152 _print = malloc(alen);
153 memcpy(_print, arg, alen);
156 else if (strncmp(opt, "-attribute", olen) == 0)
158 if (arg == 0) SHOW_NOVAL(opt);
159 alen = strlen(arg)+1;
160 if (_attribute) free(_attribute);
161 _attribute = malloc(alen);
162 memcpy(_attribute, arg, alen);
165 else if (strncmp(opt, "-list-filenames", olen) == 0)
166 { /* undocumented test argument */
170 else if (opt[0] == '-')
172 printf("Unknown option %s\n", opt);
180 _filenames = (char **)malloc(sizeof(char*));
184 char **ptr = (char **)realloc(_filenames, _fcount*sizeof(char*));
187 printf("Out of memory.\n\n");
193 alen = strlen(opt)+1;
194 _filenames[pos] = malloc(alen);
195 memcpy(_filenames[pos], opt, alen);
201 void walk_the_tree(size_t num, void *xid, char *tree)
203 unsigned int i, no_elements;
205 if (!tree) /* last node from the tree */
207 void *xmid = xmlMarkId(xid);
210 no_elements = xmlNodeGetNum(xid, _print);
211 for (i=0; i<no_elements; i++)
213 if (xmlNodeGetPos(xid, xmid, _print, i) != 0)
215 char value[STRING_LEN];
217 xmlCopyString(xmid, (char *)&value, STRING_LEN);
218 if (_value && _attribute)
220 if (!xmlAttributeCompareString(xmid, _attribute, _value))
222 printf("%s: <%s %s=\"%s\">%s</%s>\n",
223 _filenames[num], _print, _attribute, _value,
229 printf("%s: <%s>%s</%s>\n",
230 _filenames[num], _print, value, _print);
236 else if (xmid && _value)
238 no_elements = xmlNodeGetNum(xmid, _element);
239 for (i=0; i<no_elements; i++)
241 if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
243 char nodename[NODE_NAME_LEN];
245 xmlNodeCopyName(xmid, (char *)&nodename, NODE_NAME_LEN);
246 if (xmlCompareString(xmid, _value) == 0)
248 printf("%s: <%s>%s</%s>\n",
249 _filenames[num], nodename, _value, nodename);
255 else if (xmid && _element)
257 char parentname[NODE_NAME_LEN];
259 xmlNodeCopyName(xid, (char *)&parentname, NODE_NAME_LEN);
261 no_elements = xmlNodeGetNum(xmid, _element);
262 for (i=0; i<no_elements; i++)
264 if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
266 char nodename[NODE_NAME_LEN];
268 xmlNodeCopyName(xmid, (char *)&nodename, NODE_NAME_LEN);
269 if (!strncasecmp((char*)&nodename, _element, NODE_NAME_LEN))
271 char value[NODE_NAME_LEN];
272 xmlCopyString(xmid, (char *)&value, NODE_NAME_LEN);
273 printf("%s: <%s> <%s>%s</%s> </%s>\n",
274 _filenames[num], parentname, nodename, value,
275 nodename, parentname);
280 else printf("Error executing xmlMarkId\n");
282 else if (xid) /* walk the rest of the tree */
288 if (*elem == '/') elem++;
290 next = strchr(elem, '/');
292 xmid = xmlMarkId(xid);
300 no_elements = xmlNodeGetNum(xid, elem);
301 for (i=0; i<no_elements; i++)
303 if (xmlNodeGetPos(xid, xmid, elem, i) != 0)
304 walk_the_tree(num, xmid, next);
314 else printf("Error executing xmlMarkId\n");
318 void grep_file(unsigned num)
322 xid = xmlOpen(_filenames[num]);
325 void *xrid = xmlMarkId(xid);
328 walk_the_tree(num, xrid, _root);
330 r = xmlErrorGetNo(xrid, 0);
333 size_t n = xmlErrorGetLineNo(xrid, 0);
334 size_t c = xmlErrorGetColumnNo(xrid, 0);
335 const char *s = xmlErrorGetString(xrid, 1); /* clear the error */
336 printf("%s: at line %u, column %u: '%s'\n",_filenames[num], n,c, s);
343 fprintf(stderr, "Error reading file '%s'\n", _filenames[num]);
350 void grep_file_buffer(unsigned num)
356 fd = open(_filenames[num], O_RDONLY);
359 printf("read error opening file '%s'\n", _filenames[num]);
364 buf = malloc(st.st_size);
367 printf("unable to allocate enough memory for reading.\n");
371 res = read(fd, buf, st.st_size);
374 printf("unable to read from file '%s'.\n", _filenames[num]);
379 xid = xmlInitBuffer(buf, st.st_size);
382 void *xrid = xmlMarkId(xid);
385 walk_the_tree(num, xrid, _root);
387 r = xmlErrorGetNo(xrid, 0);
390 size_t n = xmlErrorGetLineNo(xrid, 0);
391 size_t c = xmlErrorGetColumnNo(xrid, 0);
392 const char *s = xmlErrorGetString(xrid, 1); /* clear the error */
393 printf("%s: at line %u, column %u: '%s'\n",_filenames[num], n,c, s);
400 fprintf(stderr, "Error reading file '%s'\n", _filenames[num]);
408 main (int argc, char **argv)
418 int ret = parse_option(argv, i, argc);
422 if (_root == 0) _root = (char *)_static_root;
423 if (_element == 0) _element = (char *)_static_element;
425 for (u=0; u<_fcount; u++)