Util: xml_extract: add node_exist option
[lttng-tools.git] / tests / regression / tools / mi / extract_xml.c
1 /*
2 * Copyright (C) 2014 - Jonathan Rajotte <jonathan.r.julien@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 */
16
17 /*
18 * Usage: extract_xml [-v|-e] xml_path xpath_expression
19 * Evaluate XPath expression and prints result node set.
20 * args[1] path to the xml file
21 * args[2] xpath expression to extract
22 * If -e look if node exist return "true" else nothing
23 * If -v is set the name of the node will appear with his value delimited by
24 * a semicolon(;)
25 * Ex:
26 * Command:extract_xml ../file.xml /test/node/text()
27 * Output:
28 * a
29 * b
30 * c
31 * With -v
32 * node;a;
33 * node;b;
34 * node;c;
35 */
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <assert.h>
40 #include <unistd.h>
41
42 #include <libxml/tree.h>
43 #include <libxml/parser.h>
44 #include <libxml/xpath.h>
45 #include <libxml/xpathInternals.h>
46
47 #if defined(LIBXML_XPATH_ENABLED)
48
49
50 int opt_verbose;
51 int node_exist;
52
53 /**
54 * print_xpath_nodes:
55 * nodes: the nodes set.
56 * output: the output file handle.
57 *
58 * Print the node content to the file
59 */
60 static int print_xpath_nodes(xmlDocPtr doc, xmlNodeSetPtr nodes, FILE *output)
61 {
62 int ret = 0;
63 int size;
64 int i;
65
66 xmlNodePtr cur;
67 xmlChar *node_child_value_string = NULL;
68
69 assert(output);
70 size = (nodes) ? nodes->nodeNr : 0;
71
72 for (i = 0; i < size; ++i) {
73 assert(nodes->nodeTab[i]);
74
75 if (nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
76 fprintf(stderr, "ERR:%s\n",
77 "This executable does not support xml namespacing\n");
78 ret = -1;
79 goto end;
80 } else if (nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
81 cur = nodes->nodeTab[i];
82
83 if (xmlChildElementCount(cur) == 0) {
84 if (xmlNodeIsText(cur->children)) {
85 node_child_value_string = xmlNodeListGetString(doc,
86 cur->children, 1);
87 if (node_exist) {
88 fprintf(output, "true\n");
89 } else if (opt_verbose) {
90 fprintf(output, "%s;%s;\n", cur->name,
91 node_child_value_string);
92 } else {
93 fprintf(output, "%s\n",
94 node_child_value_string);
95 }
96 xmlFree(node_child_value_string);
97 } else {
98 /* We don't want to print non-final element */
99 if (node_exist) {
100 fprintf(output, "true\n");
101 } else {
102 fprintf(stderr, "ERR:%s\n",
103 "Xpath expression return non-final xml element");
104 ret = -1;
105 goto end;
106 }
107 }
108 } else {
109 if (node_exist) {
110 fprintf(output, "true\n");
111 } else {
112 /* We don't want to print non-final element */
113 fprintf(stderr, "ERR:%s\n",
114 "Xpath expression return non-final xml element");
115 ret = -1;
116 goto end;
117 }
118 }
119
120 } else {
121 cur = nodes->nodeTab[i];
122 if (node_exist) {
123 fprintf(output, "true\n");
124 } else if (opt_verbose) {
125 fprintf(output, "%s;%s;\n", cur->parent->name, cur->content);
126 } else {
127 fprintf(output, "%s\n", cur->content);
128 }
129 }
130 }
131 /* Command Success */
132 ret = 0;
133
134 end:
135 return ret;
136 }
137
138 /*
139 * Extract element corresponding to xpath
140 * xml_path The path to the xml file
141 * xpath: The xpath to evaluate.
142 *
143 * Evaluate an xpath expression onto an xml file.
144 * and print the result one by line.
145 *
146 * Returns 0 on success and a negative value otherwise.
147 */
148 static int extract_xpath(const char *xml_path, const xmlChar *xpath)
149 {
150 xmlDocPtr doc = NULL;
151 xmlXPathContextPtr xpathCtx = NULL;
152 xmlXPathObjectPtr xpathObj = NULL;
153
154 assert(xml_path);
155 assert(xpath);
156
157 /* Parse the xml file */
158 doc = xmlParseFile(xml_path);
159 if (!doc) {
160 fprintf(stderr, "ERR parsing: xml file invalid \"%s\"\n", xml_path);
161 return -1;
162 }
163
164 /* Initialize a xpath context */
165 xpathCtx = xmlXPathNewContext(doc);
166 if (!xpathCtx) {
167 fprintf(stderr, "ERR: XPath context invalid\n");
168 xmlFreeDoc(doc);
169 return -1;
170 }
171
172 /* Evaluate xpath expression */
173 xpathObj = xmlXPathEvalExpression(xpath, xpathCtx);
174 if (!xpathObj) {
175 fprintf(stderr, "ERR: invalid xpath expression \"%s\"\n", xpath);
176 xmlXPathFreeContext(xpathCtx);
177 xmlFreeDoc(doc);
178 return -1;
179 }
180
181 /* Print results */
182 if (print_xpath_nodes(doc, xpathObj->nodesetval, stdout)) {
183 xmlXPathFreeObject(xpathObj);
184 xmlXPathFreeContext(xpathCtx);
185 xmlFreeDoc(doc);
186 return -1;
187 }
188
189 /* Cleanup */
190 xmlXPathFreeObject(xpathObj);
191 xmlXPathFreeContext(xpathCtx);
192 xmlFreeDoc(doc);
193
194 return 0;
195 }
196
197 int main(int argc, char **argv)
198 {
199 int opt;
200
201 /* Parse command line and process file */
202 while ((opt = getopt(argc, argv, "ve")) != -1) {
203 switch (opt) {
204 case 'v':
205 opt_verbose = 1;
206 break;
207 case 'e':
208 node_exist = 1;
209 break;
210 default:
211 abort();
212 }
213 }
214
215 if (!(optind + 1 < argc)) {
216 fprintf(stderr, "ERR:%s\n", "Arguments missing");
217 return -1;
218 }
219
220 /* Init libxml */
221 xmlInitParser();
222 xmlKeepBlanksDefault(0);
223 if (access(argv[optind], F_OK)) {
224 fprintf(stderr, "ERR:%s\n", "Xml path not valid");
225 return -1;
226 }
227 /* Do the main job */
228 if (extract_xpath(argv[optind], (xmlChar *)argv[optind+1])) {
229 return -1;
230 }
231
232 /* Shutdown libxml */
233 xmlCleanupParser();
234
235 return 0;
236 }
237
238 #else
239 int main(void)
240 {
241 fprintf(stderr, "XPath support not compiled in\n");
242 return -1;
243 }
244 #endif
This page took 0.033216 seconds and 4 git commands to generate.