2 * Copyright (C) 2014 EfficiOS Inc.
4 * SPDX-License-Identifier: GPL-2.0-only
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
17 * Command:extract_xml ../file.xml /test/node/text()
29 #include <common/defaults.hpp>
31 #include <libxml/parser.h>
32 #include <libxml/tree.h>
33 #include <libxml/xpath.h>
34 #include <libxml/xpathInternals.h>
41 namespace ll
= lttng::libxml
;
43 #if defined(LIBXML_XPATH_ENABLED)
45 static int opt_verbose
;
46 static int node_exist
;
47 static bool result
= false;
51 * nodes: the nodes set.
52 * output: the output file handle.
54 * Print the node content to the file
56 static int print_xpath_nodes(xmlDocPtr doc
, xmlNodeSetPtr nodes
, FILE *output
)
63 xmlChar
*node_child_value_string
= nullptr;
66 size
= (nodes
) ? nodes
->nodeNr
: 0;
68 for (i
= 0; i
< size
; ++i
) {
69 LTTNG_ASSERT(nodes
->nodeTab
[i
]);
71 if (nodes
->nodeTab
[i
]->type
== XML_NAMESPACE_DECL
) {
74 "This executable does not support xml namespacing\n");
77 } else if (nodes
->nodeTab
[i
]->type
== XML_ELEMENT_NODE
) {
78 cur
= nodes
->nodeTab
[i
];
80 if (xmlChildElementCount(cur
) == 0) {
81 if (xmlNodeIsText(cur
->children
)) {
82 node_child_value_string
=
83 xmlNodeListGetString(doc
, cur
->children
, 1);
86 } else if (opt_verbose
) {
90 node_child_value_string
);
92 fprintf(output
, "%s\n", node_child_value_string
);
94 xmlFree(node_child_value_string
);
96 /* We don't want to print non-final element */
102 "Xpath expression return non-final xml element");
111 /* We don't want to print non-final element */
114 "Xpath expression return non-final xml element");
121 cur
= nodes
->nodeTab
[i
];
124 } else if (opt_verbose
) {
125 fprintf(output
, "%s;%s;\n", cur
->parent
->name
, cur
->content
);
127 fprintf(output
, "%s\n", cur
->content
);
131 /* Command Success */
138 static int register_lttng_namespace(xmlXPathContextPtr xpathCtx
)
142 xmlChar
*ns
= nullptr;
144 prefix
= xmlCharStrdup("lttng");
150 ns
= xmlCharStrdup(DEFAULT_LTTNG_MI_NAMESPACE
);
156 ret
= xmlXPathRegisterNs(xpathCtx
, prefix
, ns
);
164 * Extract element corresponding to xpath
165 * xml_path The path to the xml file
166 * xpath: The xpath to evaluate.
168 * Evaluate an xpath expression onto an xml file.
169 * and print the result one by line.
171 * Returns 0 on success and a negative value otherwise.
173 static int extract_xpath(const char *xml_path
, const xmlChar
*xpath
)
176 xmlDocPtr doc
= nullptr;
177 xmlXPathContextPtr xpathCtx
= nullptr;
178 xmlXPathObjectPtr xpathObj
= nullptr;
180 LTTNG_ASSERT(xml_path
);
183 ll::parser_ctx_uptr parserCtx
{ xmlNewParserCtxt() };
186 fprintf(stderr
, "ERR: could not allocate an XML parser context\n");
190 /* Parse the xml file */
191 doc
= xmlCtxtReadFile(parserCtx
.get(), xml_path
, nullptr, XML_PARSE_NOBLANKS
);
193 fprintf(stderr
, "ERR parsing: xml file invalid \"%s\"\n", xml_path
);
197 /* Initialize a xpath context */
198 xpathCtx
= xmlXPathNewContext(doc
);
200 fprintf(stderr
, "ERR: XPath context invalid\n");
205 /* Register the LTTng MI namespace */
206 ret
= register_lttng_namespace(xpathCtx
);
208 fprintf(stderr
, "ERR: Could not register lttng namespace\n");
209 xmlXPathFreeContext(xpathCtx
);
214 /* Evaluate xpath expression */
215 xpathObj
= xmlXPathEvalExpression(xpath
, xpathCtx
);
217 fprintf(stderr
, "ERR: invalid xpath expression \"%s\"\n", xpath
);
218 xmlXPathFreeContext(xpathCtx
);
224 if (print_xpath_nodes(doc
, xpathObj
->nodesetval
, stdout
)) {
225 xmlXPathFreeObject(xpathObj
);
226 xmlXPathFreeContext(xpathCtx
);
230 if (node_exist
&& result
) {
231 fprintf(stdout
, "true\n");
235 xmlXPathFreeObject(xpathObj
);
236 xmlXPathFreeContext(xpathCtx
);
242 int main(int argc
, char **argv
)
246 /* Parse command line and process file */
247 while ((opt
= getopt(argc
, argv
, "ve")) != -1) {
260 if (!(optind
+ 1 < argc
)) {
261 fprintf(stderr
, "ERR:%s\n", "Arguments missing");
267 if (access(argv
[optind
], F_OK
)) {
268 fprintf(stderr
, "ERR:%s\n", "Xml path not valid");
271 /* Do the main job */
272 if (extract_xpath(argv
[optind
], (xmlChar
*) argv
[optind
+ 1])) {
276 /* Shutdown libxml */
285 fprintf(stderr
, "XPath support not compiled in\n");