xref: /aosp_15_r20/external/libxml2/example/xpath1.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
1*7c568831SAndroid Build Coastguard Worker /**
2*7c568831SAndroid Build Coastguard Worker  * section: 	XPath
3*7c568831SAndroid Build Coastguard Worker  * synopsis: 	Evaluate XPath expression and prints result node set.
4*7c568831SAndroid Build Coastguard Worker  * purpose: 	Shows how to evaluate XPath expression and register
5*7c568831SAndroid Build Coastguard Worker  *          	known namespaces in XPath context.
6*7c568831SAndroid Build Coastguard Worker  * usage:	xpath1 <xml-file> <xpath-expr> [<known-ns-list>]
7*7c568831SAndroid Build Coastguard Worker  * test:	xpath1 test3.xml '//child2' > xpath1.tmp && diff xpath1.tmp $(srcdir)/xpath1.res
8*7c568831SAndroid Build Coastguard Worker  * author: 	Aleksey Sanin
9*7c568831SAndroid Build Coastguard Worker  * copy: 	see Copyright for the status of this software.
10*7c568831SAndroid Build Coastguard Worker  */
11*7c568831SAndroid Build Coastguard Worker #include <stdlib.h>
12*7c568831SAndroid Build Coastguard Worker #include <stdio.h>
13*7c568831SAndroid Build Coastguard Worker #include <string.h>
14*7c568831SAndroid Build Coastguard Worker #include <assert.h>
15*7c568831SAndroid Build Coastguard Worker 
16*7c568831SAndroid Build Coastguard Worker #include <libxml/tree.h>
17*7c568831SAndroid Build Coastguard Worker #include <libxml/parser.h>
18*7c568831SAndroid Build Coastguard Worker #include <libxml/xpath.h>
19*7c568831SAndroid Build Coastguard Worker #include <libxml/xpathInternals.h>
20*7c568831SAndroid Build Coastguard Worker 
21*7c568831SAndroid Build Coastguard Worker #if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_SAX1_ENABLED)
22*7c568831SAndroid Build Coastguard Worker 
23*7c568831SAndroid Build Coastguard Worker 
24*7c568831SAndroid Build Coastguard Worker static void usage(const char *name);
25*7c568831SAndroid Build Coastguard Worker int  execute_xpath_expression(const char* filename, const xmlChar* xpathExpr, const xmlChar* nsList);
26*7c568831SAndroid Build Coastguard Worker int  register_namespaces(xmlXPathContextPtr xpathCtx, const xmlChar* nsList);
27*7c568831SAndroid Build Coastguard Worker void print_xpath_nodes(xmlNodeSetPtr nodes, FILE* output);
28*7c568831SAndroid Build Coastguard Worker 
29*7c568831SAndroid Build Coastguard Worker int
main(int argc,char ** argv)30*7c568831SAndroid Build Coastguard Worker main(int argc, char **argv) {
31*7c568831SAndroid Build Coastguard Worker     /* Parse command line and process file */
32*7c568831SAndroid Build Coastguard Worker     if((argc < 3) || (argc > 4)) {
33*7c568831SAndroid Build Coastguard Worker 	fprintf(stderr, "Error: wrong number of arguments.\n");
34*7c568831SAndroid Build Coastguard Worker 	usage(argv[0]);
35*7c568831SAndroid Build Coastguard Worker 	return(-1);
36*7c568831SAndroid Build Coastguard Worker     }
37*7c568831SAndroid Build Coastguard Worker 
38*7c568831SAndroid Build Coastguard Worker     /* Init libxml */
39*7c568831SAndroid Build Coastguard Worker     xmlInitParser();
40*7c568831SAndroid Build Coastguard Worker     LIBXML_TEST_VERSION
41*7c568831SAndroid Build Coastguard Worker 
42*7c568831SAndroid Build Coastguard Worker     /* Do the main job */
43*7c568831SAndroid Build Coastguard Worker     if(execute_xpath_expression(argv[1], BAD_CAST argv[2], (argc > 3) ? BAD_CAST argv[3] : NULL) < 0) {
44*7c568831SAndroid Build Coastguard Worker 	usage(argv[0]);
45*7c568831SAndroid Build Coastguard Worker 	return(-1);
46*7c568831SAndroid Build Coastguard Worker     }
47*7c568831SAndroid Build Coastguard Worker 
48*7c568831SAndroid Build Coastguard Worker     return 0;
49*7c568831SAndroid Build Coastguard Worker }
50*7c568831SAndroid Build Coastguard Worker 
51*7c568831SAndroid Build Coastguard Worker /**
52*7c568831SAndroid Build Coastguard Worker  * usage:
53*7c568831SAndroid Build Coastguard Worker  * @name:		the program name.
54*7c568831SAndroid Build Coastguard Worker  *
55*7c568831SAndroid Build Coastguard Worker  * Prints usage information.
56*7c568831SAndroid Build Coastguard Worker  */
57*7c568831SAndroid Build Coastguard Worker static void
usage(const char * name)58*7c568831SAndroid Build Coastguard Worker usage(const char *name) {
59*7c568831SAndroid Build Coastguard Worker     assert(name);
60*7c568831SAndroid Build Coastguard Worker 
61*7c568831SAndroid Build Coastguard Worker     fprintf(stderr, "Usage: %s <xml-file> <xpath-expr> [<known-ns-list>]\n", name);
62*7c568831SAndroid Build Coastguard Worker     fprintf(stderr, "where <known-ns-list> is a list of known namespaces\n");
63*7c568831SAndroid Build Coastguard Worker     fprintf(stderr, "in \"<prefix1>=<href1> <prefix2>=href2> ...\" format\n");
64*7c568831SAndroid Build Coastguard Worker }
65*7c568831SAndroid Build Coastguard Worker 
66*7c568831SAndroid Build Coastguard Worker /**
67*7c568831SAndroid Build Coastguard Worker  * execute_xpath_expression:
68*7c568831SAndroid Build Coastguard Worker  * @filename:		the input XML filename.
69*7c568831SAndroid Build Coastguard Worker  * @xpathExpr:		the xpath expression for evaluation.
70*7c568831SAndroid Build Coastguard Worker  * @nsList:		the optional list of known namespaces in
71*7c568831SAndroid Build Coastguard Worker  *			"<prefix1>=<href1> <prefix2>=href2> ..." format.
72*7c568831SAndroid Build Coastguard Worker  *
73*7c568831SAndroid Build Coastguard Worker  * Parses input XML file, evaluates XPath expression and prints results.
74*7c568831SAndroid Build Coastguard Worker  *
75*7c568831SAndroid Build Coastguard Worker  * Returns 0 on success and a negative value otherwise.
76*7c568831SAndroid Build Coastguard Worker  */
77*7c568831SAndroid Build Coastguard Worker int
execute_xpath_expression(const char * filename,const xmlChar * xpathExpr,const xmlChar * nsList)78*7c568831SAndroid Build Coastguard Worker execute_xpath_expression(const char* filename, const xmlChar* xpathExpr, const xmlChar* nsList) {
79*7c568831SAndroid Build Coastguard Worker     xmlDocPtr doc;
80*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr xpathCtx;
81*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr xpathObj;
82*7c568831SAndroid Build Coastguard Worker 
83*7c568831SAndroid Build Coastguard Worker     assert(filename);
84*7c568831SAndroid Build Coastguard Worker     assert(xpathExpr);
85*7c568831SAndroid Build Coastguard Worker 
86*7c568831SAndroid Build Coastguard Worker     /* Load XML document */
87*7c568831SAndroid Build Coastguard Worker     doc = xmlParseFile(filename);
88*7c568831SAndroid Build Coastguard Worker     if (doc == NULL) {
89*7c568831SAndroid Build Coastguard Worker 	fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
90*7c568831SAndroid Build Coastguard Worker 	return(-1);
91*7c568831SAndroid Build Coastguard Worker     }
92*7c568831SAndroid Build Coastguard Worker 
93*7c568831SAndroid Build Coastguard Worker     /* Create xpath evaluation context */
94*7c568831SAndroid Build Coastguard Worker     xpathCtx = xmlXPathNewContext(doc);
95*7c568831SAndroid Build Coastguard Worker     if(xpathCtx == NULL) {
96*7c568831SAndroid Build Coastguard Worker         fprintf(stderr,"Error: unable to create new XPath context\n");
97*7c568831SAndroid Build Coastguard Worker         xmlFreeDoc(doc);
98*7c568831SAndroid Build Coastguard Worker         return(-1);
99*7c568831SAndroid Build Coastguard Worker     }
100*7c568831SAndroid Build Coastguard Worker 
101*7c568831SAndroid Build Coastguard Worker     /* Register namespaces from list (if any) */
102*7c568831SAndroid Build Coastguard Worker     if((nsList != NULL) && (register_namespaces(xpathCtx, nsList) < 0)) {
103*7c568831SAndroid Build Coastguard Worker         fprintf(stderr,"Error: failed to register namespaces list \"%s\"\n", nsList);
104*7c568831SAndroid Build Coastguard Worker         xmlXPathFreeContext(xpathCtx);
105*7c568831SAndroid Build Coastguard Worker         xmlFreeDoc(doc);
106*7c568831SAndroid Build Coastguard Worker         return(-1);
107*7c568831SAndroid Build Coastguard Worker     }
108*7c568831SAndroid Build Coastguard Worker 
109*7c568831SAndroid Build Coastguard Worker     /* Evaluate xpath expression */
110*7c568831SAndroid Build Coastguard Worker     xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
111*7c568831SAndroid Build Coastguard Worker     if(xpathObj == NULL) {
112*7c568831SAndroid Build Coastguard Worker         fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr);
113*7c568831SAndroid Build Coastguard Worker         xmlXPathFreeContext(xpathCtx);
114*7c568831SAndroid Build Coastguard Worker         xmlFreeDoc(doc);
115*7c568831SAndroid Build Coastguard Worker         return(-1);
116*7c568831SAndroid Build Coastguard Worker     }
117*7c568831SAndroid Build Coastguard Worker 
118*7c568831SAndroid Build Coastguard Worker     /* Print results */
119*7c568831SAndroid Build Coastguard Worker     print_xpath_nodes(xpathObj->nodesetval, stdout);
120*7c568831SAndroid Build Coastguard Worker 
121*7c568831SAndroid Build Coastguard Worker     /* Cleanup */
122*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeObject(xpathObj);
123*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeContext(xpathCtx);
124*7c568831SAndroid Build Coastguard Worker     xmlFreeDoc(doc);
125*7c568831SAndroid Build Coastguard Worker 
126*7c568831SAndroid Build Coastguard Worker     return(0);
127*7c568831SAndroid Build Coastguard Worker }
128*7c568831SAndroid Build Coastguard Worker 
129*7c568831SAndroid Build Coastguard Worker /**
130*7c568831SAndroid Build Coastguard Worker  * register_namespaces:
131*7c568831SAndroid Build Coastguard Worker  * @xpathCtx:		the pointer to an XPath context.
132*7c568831SAndroid Build Coastguard Worker  * @nsList:		the list of known namespaces in
133*7c568831SAndroid Build Coastguard Worker  *			"<prefix1>=<href1> <prefix2>=href2> ..." format.
134*7c568831SAndroid Build Coastguard Worker  *
135*7c568831SAndroid Build Coastguard Worker  * Registers namespaces from @nsList in @xpathCtx.
136*7c568831SAndroid Build Coastguard Worker  *
137*7c568831SAndroid Build Coastguard Worker  * Returns 0 on success and a negative value otherwise.
138*7c568831SAndroid Build Coastguard Worker  */
139*7c568831SAndroid Build Coastguard Worker int
register_namespaces(xmlXPathContextPtr xpathCtx,const xmlChar * nsList)140*7c568831SAndroid Build Coastguard Worker register_namespaces(xmlXPathContextPtr xpathCtx, const xmlChar* nsList) {
141*7c568831SAndroid Build Coastguard Worker     xmlChar* nsListDup;
142*7c568831SAndroid Build Coastguard Worker     xmlChar* prefix;
143*7c568831SAndroid Build Coastguard Worker     xmlChar* href;
144*7c568831SAndroid Build Coastguard Worker     xmlChar* next;
145*7c568831SAndroid Build Coastguard Worker 
146*7c568831SAndroid Build Coastguard Worker     assert(xpathCtx);
147*7c568831SAndroid Build Coastguard Worker     assert(nsList);
148*7c568831SAndroid Build Coastguard Worker 
149*7c568831SAndroid Build Coastguard Worker     nsListDup = xmlStrdup(nsList);
150*7c568831SAndroid Build Coastguard Worker     if(nsListDup == NULL) {
151*7c568831SAndroid Build Coastguard Worker 	fprintf(stderr, "Error: unable to strdup namespaces list\n");
152*7c568831SAndroid Build Coastguard Worker 	return(-1);
153*7c568831SAndroid Build Coastguard Worker     }
154*7c568831SAndroid Build Coastguard Worker 
155*7c568831SAndroid Build Coastguard Worker     next = nsListDup;
156*7c568831SAndroid Build Coastguard Worker     while(next != NULL) {
157*7c568831SAndroid Build Coastguard Worker 	/* skip spaces */
158*7c568831SAndroid Build Coastguard Worker 	while((*next) == ' ') next++;
159*7c568831SAndroid Build Coastguard Worker 	if((*next) == '\0') break;
160*7c568831SAndroid Build Coastguard Worker 
161*7c568831SAndroid Build Coastguard Worker 	/* find prefix */
162*7c568831SAndroid Build Coastguard Worker 	prefix = next;
163*7c568831SAndroid Build Coastguard Worker 	next = (xmlChar*)xmlStrchr(next, '=');
164*7c568831SAndroid Build Coastguard Worker 	if(next == NULL) {
165*7c568831SAndroid Build Coastguard Worker 	    fprintf(stderr,"Error: invalid namespaces list format\n");
166*7c568831SAndroid Build Coastguard Worker 	    xmlFree(nsListDup);
167*7c568831SAndroid Build Coastguard Worker 	    return(-1);
168*7c568831SAndroid Build Coastguard Worker 	}
169*7c568831SAndroid Build Coastguard Worker 	*(next++) = '\0';
170*7c568831SAndroid Build Coastguard Worker 
171*7c568831SAndroid Build Coastguard Worker 	/* find href */
172*7c568831SAndroid Build Coastguard Worker 	href = next;
173*7c568831SAndroid Build Coastguard Worker 	next = (xmlChar*)xmlStrchr(next, ' ');
174*7c568831SAndroid Build Coastguard Worker 	if(next != NULL) {
175*7c568831SAndroid Build Coastguard Worker 	    *(next++) = '\0';
176*7c568831SAndroid Build Coastguard Worker 	}
177*7c568831SAndroid Build Coastguard Worker 
178*7c568831SAndroid Build Coastguard Worker 	/* do register namespace */
179*7c568831SAndroid Build Coastguard Worker 	if(xmlXPathRegisterNs(xpathCtx, prefix, href) != 0) {
180*7c568831SAndroid Build Coastguard Worker 	    fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
181*7c568831SAndroid Build Coastguard Worker 	    xmlFree(nsListDup);
182*7c568831SAndroid Build Coastguard Worker 	    return(-1);
183*7c568831SAndroid Build Coastguard Worker 	}
184*7c568831SAndroid Build Coastguard Worker     }
185*7c568831SAndroid Build Coastguard Worker 
186*7c568831SAndroid Build Coastguard Worker     xmlFree(nsListDup);
187*7c568831SAndroid Build Coastguard Worker     return(0);
188*7c568831SAndroid Build Coastguard Worker }
189*7c568831SAndroid Build Coastguard Worker 
190*7c568831SAndroid Build Coastguard Worker /**
191*7c568831SAndroid Build Coastguard Worker  * print_xpath_nodes:
192*7c568831SAndroid Build Coastguard Worker  * @nodes:		the nodes set.
193*7c568831SAndroid Build Coastguard Worker  * @output:		the output file handle.
194*7c568831SAndroid Build Coastguard Worker  *
195*7c568831SAndroid Build Coastguard Worker  * Prints the @nodes content to @output.
196*7c568831SAndroid Build Coastguard Worker  */
197*7c568831SAndroid Build Coastguard Worker void
print_xpath_nodes(xmlNodeSetPtr nodes,FILE * output)198*7c568831SAndroid Build Coastguard Worker print_xpath_nodes(xmlNodeSetPtr nodes, FILE* output) {
199*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur;
200*7c568831SAndroid Build Coastguard Worker     int size;
201*7c568831SAndroid Build Coastguard Worker     int i;
202*7c568831SAndroid Build Coastguard Worker 
203*7c568831SAndroid Build Coastguard Worker     assert(output);
204*7c568831SAndroid Build Coastguard Worker     size = (nodes) ? nodes->nodeNr : 0;
205*7c568831SAndroid Build Coastguard Worker 
206*7c568831SAndroid Build Coastguard Worker     fprintf(output, "Result (%d nodes):\n", size);
207*7c568831SAndroid Build Coastguard Worker     for(i = 0; i < size; ++i) {
208*7c568831SAndroid Build Coastguard Worker 	assert(nodes->nodeTab[i]);
209*7c568831SAndroid Build Coastguard Worker 
210*7c568831SAndroid Build Coastguard Worker 	if(nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
211*7c568831SAndroid Build Coastguard Worker 	    xmlNsPtr ns;
212*7c568831SAndroid Build Coastguard Worker 
213*7c568831SAndroid Build Coastguard Worker 	    ns = (xmlNsPtr)nodes->nodeTab[i];
214*7c568831SAndroid Build Coastguard Worker 	    cur = (xmlNodePtr)ns->next;
215*7c568831SAndroid Build Coastguard Worker 	    if(cur->ns) {
216*7c568831SAndroid Build Coastguard Worker 	        fprintf(output, "= namespace \"%s\"=\"%s\" for node %s:%s\n",
217*7c568831SAndroid Build Coastguard Worker 		    ns->prefix, ns->href, cur->ns->href, cur->name);
218*7c568831SAndroid Build Coastguard Worker 	    } else {
219*7c568831SAndroid Build Coastguard Worker 	        fprintf(output, "= namespace \"%s\"=\"%s\" for node %s\n",
220*7c568831SAndroid Build Coastguard Worker 		    ns->prefix, ns->href, cur->name);
221*7c568831SAndroid Build Coastguard Worker 	    }
222*7c568831SAndroid Build Coastguard Worker 	} else if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
223*7c568831SAndroid Build Coastguard Worker 	    cur = nodes->nodeTab[i];
224*7c568831SAndroid Build Coastguard Worker 	    if(cur->ns) {
225*7c568831SAndroid Build Coastguard Worker     	        fprintf(output, "= element node \"%s:%s\"\n",
226*7c568831SAndroid Build Coastguard Worker 		    cur->ns->href, cur->name);
227*7c568831SAndroid Build Coastguard Worker 	    } else {
228*7c568831SAndroid Build Coastguard Worker     	        fprintf(output, "= element node \"%s\"\n",
229*7c568831SAndroid Build Coastguard Worker 		    cur->name);
230*7c568831SAndroid Build Coastguard Worker 	    }
231*7c568831SAndroid Build Coastguard Worker 	} else {
232*7c568831SAndroid Build Coastguard Worker 	    cur = nodes->nodeTab[i];
233*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "= node \"%s\": type %d\n", cur->name, cur->type);
234*7c568831SAndroid Build Coastguard Worker 	}
235*7c568831SAndroid Build Coastguard Worker     }
236*7c568831SAndroid Build Coastguard Worker }
237*7c568831SAndroid Build Coastguard Worker 
238*7c568831SAndroid Build Coastguard Worker #else
main(void)239*7c568831SAndroid Build Coastguard Worker int main(void) {
240*7c568831SAndroid Build Coastguard Worker     fprintf(stderr, "XPath support not compiled in\n");
241*7c568831SAndroid Build Coastguard Worker     return 0;
242*7c568831SAndroid Build Coastguard Worker }
243*7c568831SAndroid Build Coastguard Worker #endif
244