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