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