tizen 2.3.1 release
[external/libxml2.git] / testC14N.c
1 /*
2  * Canonical XML implementation test program
3  * (http://www.w3.org/TR/2001/REC-xml-c14n-20010315)
4  *
5  * See Copyright for the status of this software.
6  * 
7  * Author: Aleksey Sanin <aleksey@aleksey.com>
8  */
9 #include "libxml.h"
10 #if defined(LIBXML_C14N_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
11
12 #include <stdio.h>
13 #include <string.h>
14 #ifdef HAVE_UNISTD_H
15 #include <unistd.h>
16 #endif
17 #ifdef HAVE_STDLIB_H
18 #include <stdlib.h>
19 #endif
20
21 #include <libxml/xmlmemory.h>
22 #include <libxml/parser.h>
23 #include <libxml/xpath.h>
24 #include <libxml/xpathInternals.h>
25
26 #include <libxml/c14n.h>
27
28
29 static void usage(const char *name) {
30     fprintf(stderr,
31         "Usage: %s <mode> <xml-file> [<xpath-expr>] [<inclusive-ns-list>]\n",
32             name);
33     fprintf(stderr, "where <mode> is one of following:\n");
34     fprintf(stderr,
35         "--with-comments       \t XML file canonicalization v1.0 w comments \n");
36     fprintf(stderr,
37         "--without-comments    \t XML file canonicalization v1.0 w/o comments\n");
38     fprintf(stderr,
39         "--1-1-with-comments       \t XML file canonicalization v1.1 w comments\n");
40     fprintf(stderr,
41         "--1-1-without-comments    \t XML file canonicalization v1.1 w/o comments\n");
42     fprintf(stderr,
43     "--exc-with-comments   \t Exclusive XML file canonicalization v1.0 w comments\n");
44     fprintf(stderr,
45     "--exc-without-comments\t Exclusive XML file canonicalization v1.0 w/o comments\n");
46 }
47
48 static xmlXPathObjectPtr
49 load_xpath_expr (xmlDocPtr parent_doc, const char* filename);
50
51 static xmlChar **parse_list(xmlChar *str);
52
53 /* static void print_xpath_nodes(xmlNodeSetPtr nodes); */
54
55 static int 
56 test_c14n(const char* xml_filename, int with_comments, int mode,
57         const char* xpath_filename, xmlChar **inclusive_namespaces) {
58     xmlDocPtr doc;
59     xmlXPathObjectPtr xpath = NULL; 
60     xmlChar *result = NULL;
61     int ret;
62
63     /*
64      * build an XML tree from a the file; we need to add default
65      * attributes and resolve all character and entities references
66      */
67     xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
68     xmlSubstituteEntitiesDefault(1);
69
70     doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
71     if (doc == NULL) {
72         fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
73         return(-1);
74     }
75     
76     /*
77      * Check the document is of the right kind
78      */    
79     if(xmlDocGetRootElement(doc) == NULL) {
80         fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
81         xmlFreeDoc(doc);
82         return(-1);
83     }
84
85     /* 
86      * load xpath file if specified 
87      */
88     if(xpath_filename) {
89         xpath = load_xpath_expr(doc, xpath_filename);
90         if(xpath == NULL) {
91             fprintf(stderr,"Error: unable to evaluate xpath expression\n");
92             xmlFreeDoc(doc); 
93             return(-1);
94         }
95     }
96
97     /*
98      * Canonical form
99      */      
100     /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
101     ret = xmlC14NDocDumpMemory(doc, 
102             (xpath) ? xpath->nodesetval : NULL, 
103             mode, inclusive_namespaces,
104             with_comments, &result);
105     if(ret >= 0) {
106         if(result != NULL) {
107             write(1, result, ret);
108             xmlFree(result);          
109         }
110     } else {
111         fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
112         if(result != NULL) xmlFree(result);
113         xmlFreeDoc(doc); 
114         return(-1);
115     }
116         
117     /*
118      * Cleanup
119      */ 
120     if(xpath != NULL) xmlXPathFreeObject(xpath);
121     xmlFreeDoc(doc);    
122
123     return(ret);
124 }
125
126 int main(int argc, char **argv) {
127     int ret = -1;
128     
129     /*
130      * Init libxml
131      */     
132     xmlInitParser();
133     LIBXML_TEST_VERSION
134
135     /*
136      * Parse command line and process file
137      */
138     if( argc < 3 ) {
139         fprintf(stderr, "Error: wrong number of arguments.\n");
140         usage(argv[0]);
141     } else if(strcmp(argv[1], "--with-comments") == 0) {
142         ret = test_c14n(argv[2], 1, XML_C14N_1_0, (argc > 3) ? argv[3] : NULL, NULL);
143     } else if(strcmp(argv[1], "--without-comments") == 0) {
144         ret = test_c14n(argv[2], 0, XML_C14N_1_0, (argc > 3) ? argv[3] : NULL, NULL);
145     } else if(strcmp(argv[1], "--1-1-with-comments") == 0) {
146         ret = test_c14n(argv[2], 1, XML_C14N_1_1, (argc > 3) ? argv[3] : NULL, NULL);
147     } else if(strcmp(argv[1], "--1-1-without-comments") == 0) {
148         ret = test_c14n(argv[2], 0, XML_C14N_1_1, (argc > 3) ? argv[3] : NULL, NULL);
149     } else if(strcmp(argv[1], "--exc-with-comments") == 0) {
150         xmlChar **list;
151         
152         /* load exclusive namespace from command line */
153         list = (argc > 4) ? parse_list((xmlChar *)argv[4]) : NULL;
154         ret = test_c14n(argv[2], 1, XML_C14N_EXCLUSIVE_1_0, (argc > 3) ? argv[3] : NULL, list);
155         if(list != NULL) xmlFree(list);
156     } else if(strcmp(argv[1], "--exc-without-comments") == 0) {
157         xmlChar **list;
158         
159         /* load exclusive namespace from command line */
160         list = (argc > 4) ? parse_list((xmlChar *)argv[4]) : NULL;
161         ret = test_c14n(argv[2], 0, XML_C14N_EXCLUSIVE_1_0, (argc > 3) ? argv[3] : NULL, list);
162         if(list != NULL) xmlFree(list);
163     } else {
164         fprintf(stderr, "Error: bad option.\n");
165         usage(argv[0]);
166     }
167
168     /* 
169      * Shutdown libxml
170      */
171     xmlCleanupParser();
172     xmlMemoryDump();
173
174     return((ret >= 0) ? 0 : 1);
175 }
176
177 /*
178  * Macro used to grow the current buffer.
179  */
180 #define growBufferReentrant() {                                         \
181     buffer_size *= 2;                                                   \
182     buffer = (xmlChar **)                                               \
183                 xmlRealloc(buffer, buffer_size * sizeof(xmlChar*));     \
184     if (buffer == NULL) {                                               \
185         perror("realloc failed");                                       \
186         return(NULL);                                                   \
187     }                                                                   \
188 }
189
190 static xmlChar **
191 parse_list(xmlChar *str) {
192     xmlChar **buffer;
193     xmlChar **out = NULL;
194     int buffer_size = 0;
195     int len;
196
197     if(str == NULL) {
198         return(NULL);
199     }
200
201     len = xmlStrlen(str);
202     if((str[0] == '\'') && (str[len - 1] == '\'')) {
203         str[len - 1] = '\0';
204         str++;
205     }
206     /*
207      * allocate an translation buffer.
208      */
209     buffer_size = 1000;
210     buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
211     if (buffer == NULL) {
212         perror("malloc failed");
213         return(NULL);
214     }
215     out = buffer;
216
217     while(*str != '\0') {
218         if (out - buffer > buffer_size - 10) {
219             int indx = out - buffer;
220
221             growBufferReentrant();
222             out = &buffer[indx];
223         }
224         (*out++) = str;
225         while(*str != ',' && *str != '\0') ++str;
226         if(*str == ',') *(str++) = '\0';
227     }
228     (*out) = NULL;
229     return buffer;
230 }
231
232 static xmlXPathObjectPtr
233 load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
234     xmlXPathObjectPtr xpath; 
235     xmlDocPtr doc;
236     xmlChar *expr;
237     xmlXPathContextPtr ctx; 
238     xmlNodePtr node;
239     xmlNsPtr ns;
240     
241     /*
242      * load XPath expr as a file
243      */
244     xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
245     xmlSubstituteEntitiesDefault(1);
246
247     doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
248     if (doc == NULL) {
249         fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
250         return(NULL);
251     }
252     
253     /*
254      * Check the document is of the right kind
255      */    
256     if(xmlDocGetRootElement(doc) == NULL) {
257         fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
258         xmlFreeDoc(doc);
259         return(NULL);
260     }
261
262     node = doc->children;
263     while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
264         node = node->next;
265     }
266     
267     if(node == NULL) {   
268         fprintf(stderr,"Error: XPath element expected in the file  \"%s\"\n", filename);
269         xmlFreeDoc(doc);
270         return(NULL);
271     }
272
273     expr = xmlNodeGetContent(node);
274     if(expr == NULL) {
275         fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
276         xmlFreeDoc(doc);
277         return(NULL);
278     }
279
280     ctx = xmlXPathNewContext(parent_doc);
281     if(ctx == NULL) {
282         fprintf(stderr,"Error: unable to create new context\n");
283         xmlFree(expr); 
284         xmlFreeDoc(doc); 
285         return(NULL);
286     }
287
288     /*
289      * Register namespaces
290      */
291     ns = node->nsDef;
292     while(ns != NULL) {
293         if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
294             fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
295             xmlFree(expr); 
296             xmlXPathFreeContext(ctx); 
297             xmlFreeDoc(doc); 
298             return(NULL);
299         }
300         ns = ns->next;
301     }
302
303     /*  
304      * Evaluate xpath
305      */
306     xpath = xmlXPathEvalExpression(expr, ctx);
307     if(xpath == NULL) {
308         fprintf(stderr,"Error: unable to evaluate xpath expression\n");
309         xmlFree(expr); 
310         xmlXPathFreeContext(ctx); 
311         xmlFreeDoc(doc); 
312         return(NULL);
313     }
314
315     /* print_xpath_nodes(xpath->nodesetval); */
316
317     xmlFree(expr); 
318     xmlXPathFreeContext(ctx); 
319     xmlFreeDoc(doc); 
320     return(xpath);
321 }
322
323 /*
324 static void
325 print_xpath_nodes(xmlNodeSetPtr nodes) {
326     xmlNodePtr cur;
327     int i;
328     
329     if(nodes == NULL ){ 
330         fprintf(stderr, "Error: no nodes set defined\n");
331         return;
332     }
333     
334     fprintf(stderr, "Nodes Set:\n-----\n");
335     for(i = 0; i < nodes->nodeNr; ++i) {
336         if(nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
337             xmlNsPtr ns;
338             
339             ns = (xmlNsPtr)nodes->nodeTab[i];
340             cur = (xmlNodePtr)ns->next;
341             fprintf(stderr, "namespace \"%s\"=\"%s\" for node %s:%s\n", 
342                     ns->prefix, ns->href,
343                     (cur->ns) ? cur->ns->prefix : BAD_CAST "", cur->name);
344         } else if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
345             cur = nodes->nodeTab[i];    
346             fprintf(stderr, "element node \"%s:%s\"\n", 
347                     (cur->ns) ? cur->ns->prefix : BAD_CAST "", cur->name);
348         } else {
349             cur = nodes->nodeTab[i];    
350             fprintf(stderr, "node \"%s\": type %d\n", cur->name, cur->type);
351         }
352     }
353 }
354 */
355
356 #else
357 #include <stdio.h>
358 int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
359     printf("%s : XPath/Canonicalization and output support not compiled in\n", argv[0]);
360     return(0);
361 }
362 #endif /* LIBXML_C14N_ENABLED */
363
364