2 * Canonical XML implementation test program
3 * (http://www.w3.org/TR/2001/REC-xml-c14n-20010315)
5 * See Copyright for the status of this software.
7 * Author: Aleksey Sanin <aleksey@aleksey.com>
10 #if defined(LIBXML_C14N_ENABLED)
21 #include <libxml/xmlmemory.h>
22 #include <libxml/parser.h>
23 #include <libxml/xpath.h>
24 #include <libxml/xpathInternals.h>
26 #include <libxml/c14n.h>
29 static void usage(const char *name) {
31 "Usage: %s <mode> <xml-file> [<xpath-expr>] [<inclusive-ns-list>]\n",
33 fprintf(stderr, "where <mode> is one of following:\n");
35 "--with-comments \t XML file canonization w comments\n");
37 "--without-comments \t XML file canonization w/o comments\n");
39 "--exc-with-comments \t Exclusive XML file canonization w comments\n");
41 "--exc-without-comments\t Exclusive XML file canonization w/o comments\n");
44 static xmlXPathObjectPtr
45 load_xpath_expr (xmlDocPtr parent_doc, const char* filename);
47 static xmlChar **parse_list(xmlChar *str);
49 /* static void print_xpath_nodes(xmlNodeSetPtr nodes); */
52 test_c14n(const char* xml_filename, int with_comments, int exclusive,
53 const char* xpath_filename, xmlChar **inclusive_namespaces) {
55 xmlXPathObjectPtr xpath = NULL;
56 xmlChar *result = NULL;
60 * build an XML tree from a the file; we need to add default
61 * attributes and resolve all character and entities references
63 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
64 xmlSubstituteEntitiesDefault(1);
66 doc = xmlParseFile(xml_filename);
68 fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
73 * Check the document is of the right kind
75 if(xmlDocGetRootElement(doc) == NULL) {
76 fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
82 * load xpath file if specified
85 xpath = load_xpath_expr(doc, xpath_filename);
87 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
96 /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
97 ret = xmlC14NDocDumpMemory(doc,
98 (xpath) ? xpath->nodesetval : NULL,
99 exclusive, inclusive_namespaces,
100 with_comments, &result);
103 write(1, result, ret);
107 fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
108 if(result != NULL) xmlFree(result);
116 if(xpath != NULL) xmlXPathFreeObject(xpath);
122 int main(int argc, char **argv) {
132 * Parse command line and process file
135 fprintf(stderr, "Error: wrong number of arguments.\n");
137 } else if(strcmp(argv[1], "--with-comments") == 0) {
138 ret = test_c14n(argv[2], 1, 0, (argc > 3) ? argv[3] : NULL, NULL);
139 } else if(strcmp(argv[1], "--without-comments") == 0) {
140 ret = test_c14n(argv[2], 0, 0, (argc > 3) ? argv[3] : NULL, NULL);
141 } else if(strcmp(argv[1], "--exc-with-comments") == 0) {
144 /* load exclusive namespace from command line */
145 list = (argc > 4) ? parse_list((xmlChar *)argv[4]) : NULL;
146 ret = test_c14n(argv[2], 1, 1, (argc > 3) ? argv[3] : NULL, list);
147 if(list != NULL) xmlFree(list);
148 } else if(strcmp(argv[1], "--exc-without-comments") == 0) {
151 /* load exclusive namespace from command line */
152 list = (argc > 4) ? parse_list((xmlChar *)argv[4]) : NULL;
153 ret = test_c14n(argv[2], 0, 1, (argc > 3) ? argv[3] : NULL, list);
154 if(list != NULL) xmlFree(list);
156 fprintf(stderr, "Error: bad option.\n");
166 return((ret >= 0) ? 0 : 1);
170 * Macro used to grow the current buffer.
172 #define growBufferReentrant() { \
174 buffer = (xmlChar **) \
175 xmlRealloc(buffer, buffer_size * sizeof(xmlChar*)); \
176 if (buffer == NULL) { \
177 perror("realloc failed"); \
183 parse_list(xmlChar *str) {
185 xmlChar **out = NULL;
193 len = xmlStrlen(str);
194 if((str[0] == '\'') && (str[len - 1] == '\'')) {
200 * allocate an translation buffer.
203 buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
204 if (buffer == NULL) {
205 perror("malloc failed");
210 while(*str != '\0') {
211 if (out - buffer > buffer_size - 10) {
212 int indx = out - buffer;
214 growBufferReentrant();
218 while(*str != ',' && *str != '\0') ++str;
219 if(*str == ',') *(str++) = '\0';
225 static xmlXPathObjectPtr
226 load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
227 xmlXPathObjectPtr xpath;
230 xmlXPathContextPtr ctx;
235 * load XPath expr as a file
237 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
238 xmlSubstituteEntitiesDefault(1);
240 doc = xmlParseFile(filename);
242 fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
247 * Check the document is of the right kind
249 if(xmlDocGetRootElement(doc) == NULL) {
250 fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
255 node = doc->children;
256 while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
261 fprintf(stderr,"Error: XPath element expected in the file \"%s\"\n", filename);
266 expr = xmlNodeGetContent(node);
268 fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
273 ctx = xmlXPathNewContext(parent_doc);
275 fprintf(stderr,"Error: unable to create new context\n");
282 * Register namespaces
286 if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
287 fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
289 xmlXPathFreeContext(ctx);
299 xpath = xmlXPathEvalExpression(expr, ctx);
301 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
303 xmlXPathFreeContext(ctx);
308 /* print_xpath_nodes(xpath->nodesetval); */
311 xmlXPathFreeContext(ctx);
318 print_xpath_nodes(xmlNodeSetPtr nodes) {
323 fprintf(stderr, "Error: no nodes set defined\n");
327 fprintf(stderr, "Nodes Set:\n-----\n");
328 for(i = 0; i < nodes->nodeNr; ++i) {
329 if(nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
332 ns = (xmlNsPtr)nodes->nodeTab[i];
333 cur = (xmlNodePtr)ns->next;
334 fprintf(stderr, "namespace \"%s\"=\"%s\" for node %s:%s\n",
335 ns->prefix, ns->href,
336 (cur->ns) ? cur->ns->prefix : BAD_CAST "", cur->name);
337 } else if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
338 cur = nodes->nodeTab[i];
339 fprintf(stderr, "element node \"%s:%s\"\n",
340 (cur->ns) ? cur->ns->prefix : BAD_CAST "", cur->name);
342 cur = nodes->nodeTab[i];
343 fprintf(stderr, "node \"%s\": type %d\n", cur->name, cur->type);
351 int main(int argc, char **argv) {
352 printf("%s : XPath/Canonicalization support not compiled in\n", argv[0]);
355 #endif /* LIBXML_C14N_ENABLED */