3 * synopsis: Evaluate XPath expression and prints result node set.
4 * purpose: Shows how to evaluate XPath expression and register
5 * known namespaces in XPath context.
6 * usage: xpath1 <xml-file> <xpath-expr> [<known-ns-list>]
7 * test: ./xpath1 test3.xml '//child2' > xpath1.tmp ; diff xpath1.tmp xpath1.res ; rm xpath1.tmp
8 * author: Aleksey Sanin
9 * copy: see Copyright for the status of this software.
16 #include <libxml/tree.h>
17 #include <libxml/parser.h>
18 #include <libxml/xpath.h>
19 #include <libxml/xpathInternals.h>
21 #if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_SAX1_ENABLED)
24 static void usage(const char *name
);
25 int execute_xpath_expression(const char* filename
, const xmlChar
* xpathExpr
, const xmlChar
* nsList
);
26 int register_namespaces(xmlXPathContextPtr xpathCtx
, const xmlChar
* nsList
);
27 void print_xpath_nodes(xmlNodeSetPtr nodes
, FILE* output
);
30 main(int argc
, char **argv
) {
31 /* Parse command line and process file */
32 if((argc
< 3) || (argc
> 4)) {
33 fprintf(stderr
, "Error: wrong number of arguments.\n");
43 if(execute_xpath_expression(argv
[1], BAD_CAST argv
[2], (argc
> 3) ? BAD_CAST argv
[3] : NULL
) < 0) {
52 * this is to debug memory for regression tests
60 * @name: the program name.
62 * Prints usage information.
65 usage(const char *name
) {
68 fprintf(stderr
, "Usage: %s <xml-file> <xpath-expr> [<known-ns-list>]\n", name
);
69 fprintf(stderr
, "where <known-ns-list> is a list of known namespaces\n");
70 fprintf(stderr
, "in \"<prefix1>=<href1> <prefix2>=href2> ...\" format\n");
74 * execute_xpath_expression:
75 * @filename: the input XML filename.
76 * @xpathExpr: the xpath expression for evaluation.
77 * @nsList: the optional list of known namespaces in
78 * "<prefix1>=<href1> <prefix2>=href2> ..." format.
80 * Parses input XML file, evaluates XPath expression and prints results.
82 * Returns 0 on success and a negative value otherwise.
85 execute_xpath_expression(const char* filename
, const xmlChar
* xpathExpr
, const xmlChar
* nsList
) {
87 xmlXPathContextPtr xpathCtx
;
88 xmlXPathObjectPtr xpathObj
;
93 /* Load XML document */
94 doc
= xmlParseFile(filename
);
96 fprintf(stderr
, "Error: unable to parse file \"%s\"\n", filename
);
100 /* Create xpath evaluation context */
101 xpathCtx
= xmlXPathNewContext(doc
);
102 if(xpathCtx
== NULL
) {
103 fprintf(stderr
,"Error: unable to create new XPath context\n");
108 /* Register namespaces from list (if any) */
109 if((nsList
!= NULL
) && (register_namespaces(xpathCtx
, nsList
) < 0)) {
110 fprintf(stderr
,"Error: failed to register namespaces list \"%s\"\n", nsList
);
111 xmlXPathFreeContext(xpathCtx
);
116 /* Evaluate xpath expression */
117 xpathObj
= xmlXPathEvalExpression(xpathExpr
, xpathCtx
);
118 if(xpathObj
== NULL
) {
119 fprintf(stderr
,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr
);
120 xmlXPathFreeContext(xpathCtx
);
126 print_xpath_nodes(xpathObj
->nodesetval
, stdout
);
129 xmlXPathFreeObject(xpathObj
);
130 xmlXPathFreeContext(xpathCtx
);
137 * register_namespaces:
138 * @xpathCtx: the pointer to an XPath context.
139 * @nsList: the list of known namespaces in
140 * "<prefix1>=<href1> <prefix2>=href2> ..." format.
142 * Registers namespaces from @nsList in @xpathCtx.
144 * Returns 0 on success and a negative value otherwise.
147 register_namespaces(xmlXPathContextPtr xpathCtx
, const xmlChar
* nsList
) {
156 nsListDup
= xmlStrdup(nsList
);
157 if(nsListDup
== NULL
) {
158 fprintf(stderr
, "Error: unable to strdup namespaces list\n");
163 while(next
!= NULL
) {
165 while((*next
) == ' ') next
++;
166 if((*next
) == '\0') break;
170 next
= (xmlChar
*)xmlStrchr(next
, '=');
172 fprintf(stderr
,"Error: invalid namespaces list format\n");
180 next
= (xmlChar
*)xmlStrchr(next
, ' ');
185 /* do register namespace */
186 if(xmlXPathRegisterNs(xpathCtx
, prefix
, href
) != 0) {
187 fprintf(stderr
,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix
, href
);
199 * @nodes: the nodes set.
200 * @output: the output file handle.
202 * Prints the @nodes content to @output.
205 print_xpath_nodes(xmlNodeSetPtr nodes
, FILE* output
) {
211 size
= (nodes
) ? nodes
->nodeNr
: 0;
213 fprintf(output
, "Result (%d nodes):\n", size
);
214 for(i
= 0; i
< size
; ++i
) {
215 assert(nodes
->nodeTab
[i
]);
217 if(nodes
->nodeTab
[i
]->type
== XML_NAMESPACE_DECL
) {
220 ns
= (xmlNsPtr
)nodes
->nodeTab
[i
];
221 cur
= (xmlNodePtr
)ns
->next
;
223 fprintf(output
, "= namespace \"%s\"=\"%s\" for node %s:%s\n",
224 ns
->prefix
, ns
->href
, cur
->ns
->href
, cur
->name
);
226 fprintf(output
, "= namespace \"%s\"=\"%s\" for node %s\n",
227 ns
->prefix
, ns
->href
, cur
->name
);
229 } else if(nodes
->nodeTab
[i
]->type
== XML_ELEMENT_NODE
) {
230 cur
= nodes
->nodeTab
[i
];
232 fprintf(output
, "= element node \"%s:%s\"\n",
233 cur
->ns
->href
, cur
->name
);
235 fprintf(output
, "= element node \"%s\"\n",
239 cur
= nodes
->nodeTab
[i
];
240 fprintf(output
, "= node \"%s\": type %d\n", cur
->name
, cur
->type
);
247 fprintf(stderr
, "XPath support not compiled in\n");