source: trunk/third/libxml2/testC14N.c @ 18536

Revision 18536, 8.8 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18535, which included commits to RCS files with non-trunk default branches.
Line 
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)
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
29static 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 canonization w comments\n");
36    fprintf(stderr,
37        "--without-comments    \t XML file canonization w/o comments\n");
38    fprintf(stderr,
39    "--exc-with-comments   \t Exclusive XML file canonization w comments\n");
40    fprintf(stderr,
41    "--exc-without-comments\t Exclusive XML file canonization w/o comments\n");
42}
43
44static xmlXPathObjectPtr
45load_xpath_expr (xmlDocPtr parent_doc, const char* filename);
46
47static xmlChar **parse_list(xmlChar *str);
48
49static void print_xpath_nodes(xmlNodeSetPtr nodes);
50
51static int
52test_c14n(const char* xml_filename, int with_comments, int exclusive,
53        const char* xpath_filename, xmlChar **inclusive_namespaces) {
54    xmlDocPtr doc;
55    xmlXPathObjectPtr xpath = NULL;
56    xmlChar *result = NULL;
57    int ret;
58
59    /*
60     * build an XML tree from a the file; we need to add default
61     * attributes and resolve all character and entities references
62     */
63    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
64    xmlSubstituteEntitiesDefault(1);
65
66    doc = xmlParseFile(xml_filename);
67    if (doc == NULL) {
68        fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
69        return(-1);
70    }
71   
72    /*
73     * Check the document is of the right kind
74     */   
75    if(xmlDocGetRootElement(doc) == NULL) {
76        fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
77        xmlFreeDoc(doc);
78        return(-1);
79    }
80
81    /*
82     * load xpath file if specified
83     */
84    if(xpath_filename) {
85        xpath = load_xpath_expr(doc, xpath_filename);
86        if(xpath == NULL) {
87            fprintf(stderr,"Error: unable to evaluate xpath expression\n");
88            xmlFreeDoc(doc);
89            return(-1);
90        }
91    }
92
93    /*
94     * Canonical form
95     */     
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);
101    if(ret >= 0) {
102        if(result != NULL) {
103            write(1, result, ret);
104            xmlFree(result);         
105        }
106    } else {
107        fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
108        if(result != NULL) xmlFree(result);
109        xmlFreeDoc(doc);
110        return(-1);
111    }
112       
113    /*
114     * Cleanup
115     */
116    if(xpath != NULL) xmlXPathFreeObject(xpath);
117    xmlFreeDoc(doc);   
118
119    return(ret);
120}
121
122int main(int argc, char **argv) {
123    int ret = -1;
124   
125    /*
126     * Init libxml
127     */     
128    xmlInitParser();
129    LIBXML_TEST_VERSION
130
131    /*
132     * Parse command line and process file
133     */
134    if( argc < 3 ) {
135        fprintf(stderr, "Error: wrong number of arguments.\n");
136        usage(argv[0]);
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) {
142        xmlChar **list;
143       
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) {
149        xmlChar **list;
150       
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);
155    } else {
156        fprintf(stderr, "Error: bad option.\n");
157        usage(argv[0]);
158    }
159
160    /*
161     * Shutdown libxml
162     */
163    xmlCleanupParser();
164    xmlMemoryDump();
165   
166    return((ret >= 0) ? 0 : 1);
167}
168
169/*
170 * Macro used to grow the current buffer.
171 */
172#define growBufferReentrant() {                                         \
173    buffer_size *= 2;                                                   \
174    buffer = (xmlChar **)                                               \
175                xmlRealloc(buffer, buffer_size * sizeof(xmlChar*));     \
176    if (buffer == NULL) {                                               \
177        perror("realloc failed");                                       \
178        return(NULL);                                                   \
179    }                                                                   \
180}
181
182static xmlChar **
183parse_list(xmlChar *str) {
184    xmlChar **buffer;
185    xmlChar **out = NULL;
186    int buffer_size = 0;
187    int len;
188
189    if(str == NULL) {
190        return(NULL);
191    }
192
193    len = xmlStrlen(str);
194    if((str[0] == '\'') && (str[len - 1] == '\'')) {
195        str[len - 1] = '\0';
196        str++;
197        len -= 2;
198    }
199    /*
200     * allocate an translation buffer.
201     */
202    buffer_size = 1000;
203    buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
204    if (buffer == NULL) {
205        perror("malloc failed");
206        return(NULL);
207    }
208    out = buffer;
209   
210    while(*str != '\0') {
211        if (out - buffer > buffer_size - 10) {
212            int indx = out - buffer;
213
214            growBufferReentrant();
215            out = &buffer[indx];
216        }
217        (*out++) = str;
218        while(*str != ',' && *str != '\0') ++str;
219        if(*str == ',') *(str++) = '\0';
220    }
221    (*out) = NULL;
222    return buffer;
223}
224
225static xmlXPathObjectPtr
226load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
227    xmlXPathObjectPtr xpath;
228    xmlDocPtr doc;
229    xmlChar *expr;
230    xmlXPathContextPtr ctx;
231    xmlNodePtr node;
232    xmlNsPtr ns;
233   
234    /*
235     * load XPath expr as a file
236     */
237    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
238    xmlSubstituteEntitiesDefault(1);
239
240    doc = xmlParseFile(filename);
241    if (doc == NULL) {
242        fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
243        return(NULL);
244    }
245   
246    /*
247     * Check the document is of the right kind
248     */   
249    if(xmlDocGetRootElement(doc) == NULL) {
250        fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
251        xmlFreeDoc(doc);
252        return(NULL);
253    }
254
255    node = doc->children;
256    while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
257        node = node->next;
258    }
259   
260    if(node == NULL) {   
261        fprintf(stderr,"Error: XPath element expected in the file  \"%s\"\n", filename);
262        xmlFreeDoc(doc);
263        return(NULL);
264    }
265
266    expr = xmlNodeGetContent(node);
267    if(expr == NULL) {
268        fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
269        xmlFreeDoc(doc);
270        return(NULL);
271    }
272
273    ctx = xmlXPathNewContext(parent_doc);
274    if(ctx == NULL) {
275        fprintf(stderr,"Error: unable to create new context\n");
276        xmlFree(expr);
277        xmlFreeDoc(doc);
278        return(NULL);
279    }
280
281    /*
282     * Register namespaces
283     */
284    ns = node->nsDef;
285    while(ns != NULL) {
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);
288            xmlFree(expr);
289            xmlXPathFreeContext(ctx);
290            xmlFreeDoc(doc);
291            return(NULL);
292        }
293        ns = ns->next;
294    }
295
296    /* 
297     * Evaluate xpath
298     */
299    xpath = xmlXPathEvalExpression(expr, ctx);
300    if(xpath == NULL) {
301        fprintf(stderr,"Error: unable to evaluate xpath expression\n");
302        xmlFree(expr);
303        xmlXPathFreeContext(ctx);
304        xmlFreeDoc(doc);
305        return(NULL);
306    }
307
308    /* print_xpath_nodes(xpath->nodesetval); */
309
310    xmlFree(expr);
311    xmlXPathFreeContext(ctx);
312    xmlFreeDoc(doc);
313    return(xpath);
314}
315
316static void
317print_xpath_nodes(xmlNodeSetPtr nodes) {
318    xmlNodePtr cur;
319    int i;
320   
321    if(nodes == NULL ){
322        fprintf(stderr, "Error: no nodes set defined\n");
323        return;
324    }
325   
326    fprintf(stderr, "Nodes Set:\n-----\n");
327    for(i = 0; i < nodes->nodeNr; ++i) {
328        if(nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
329            xmlNsPtr ns;
330           
331            ns = (xmlNsPtr)nodes->nodeTab[i];
332            cur = (xmlNodePtr)ns->next;
333            fprintf(stderr, "namespace \"%s\"=\"%s\" for node %s:%s\n",
334                    ns->prefix, ns->href,
335                    (cur->ns) ? cur->ns->prefix : BAD_CAST "", cur->name);
336        } else if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
337            cur = nodes->nodeTab[i];   
338            fprintf(stderr, "element node \"%s:%s\"\n",
339                    (cur->ns) ? cur->ns->prefix : BAD_CAST "", cur->name);
340        } else {
341            cur = nodes->nodeTab[i];   
342            fprintf(stderr, "node \"%s\": type %d\n", cur->name, cur->type);
343        }
344    }
345}
346
347
348
349
350
351#else
352#include <stdio.h>
353int main(int argc, char **argv) {
354    printf("%s : XPath/Canonicalization support not compiled in\n", argv[0]);
355    return(0);
356}
357#endif /* LIBXML_C14N_ENABLED */
358
359
Note: See TracBrowser for help on using the repository browser.