Annotation of XML/testXPath.c, revision 1.24

1.1       daniel      1: /*
                      2:  * testXPath.c : a small tester program for XPath.
                      3:  *
                      4:  * See Copyright for the status of this software.
                      5:  *
                      6:  * Daniel.Veillard@w3.org
                      7:  */
                      8: 
                      9: #ifdef WIN32
1.16      daniel     10: #include "win32config.h"
1.1       daniel     11: #else
1.12      daniel     12: #include "config.h"
1.1       daniel     13: #endif
1.11      daniel     14: 
1.24    ! veillard   15: #include <libxml/xmlversion.h>
1.17      daniel     16: #if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_DEBUG_ENABLED)
                     17: 
1.11      daniel     18: #include <stdio.h>
                     19: #include <string.h>
                     20: 
                     21: #ifdef HAVE_SYS_TYPES_H
1.1       daniel     22: #include <sys/types.h>
1.11      daniel     23: #endif
1.1       daniel     24: #ifdef HAVE_SYS_STAT_H
                     25: #include <sys/stat.h>
                     26: #endif
                     27: #ifdef HAVE_FCNTL_H
                     28: #include <fcntl.h>
                     29: #endif
                     30: #ifdef HAVE_UNISTD_H
                     31: #include <unistd.h>
                     32: #endif
1.11      daniel     33: #ifdef HAVE_STDLIB_H
1.1       daniel     34: #include <stdlib.h>
1.11      daniel     35: #endif
                     36: 
1.1       daniel     37: 
1.17      daniel     38: #include <libxml/xpath.h>
                     39: #include <libxml/tree.h>
                     40: #include <libxml/parser.h>
                     41: #include <libxml/debugXML.h>
                     42: #include <libxml/xmlmemory.h>
1.18      veillard   43: #include <libxml/parserInternals.h>
1.19      veillard   44: #if defined(LIBXML_XPTR_ENABLED)
                     45: #include <libxml/xpointer.h>
                     46: static int xptr = 0;
                     47: #endif
1.1       daniel     48: static int debug = 0;
1.18      veillard   49: static int valid = 0;
1.5       daniel     50: static int expr = 0;
1.2       daniel     51: static xmlDocPtr document = NULL;
                     52: 
                     53: /*
                     54:  * Default document
                     55:  */
1.13      daniel     56: static xmlChar buffer[] = 
1.2       daniel     57: "<?xml version=\"1.0\"?>\n\
                     58: <EXAMPLE prop1=\"gnome is great\" prop2=\"&amp; linux too\">\n\
                     59:   <head>\n\
                     60:    <title>Welcome to Gnome</title>\n\
                     61:   </head>\n\
                     62:   <chapter>\n\
                     63:    <title>The Linux adventure</title>\n\
                     64:    <p>bla bla bla ...</p>\n\
                     65:    <image href=\"linus.gif\"/>\n\
                     66:    <p>...</p>\n\
                     67:   </chapter>\n\
1.5       daniel     68:   <chapter>\n\
                     69:    <title>Chapter 2</title>\n\
                     70:    <p>this is chapter 2 ...</p>\n\
                     71:   </chapter>\n\
                     72:   <chapter>\n\
                     73:    <title>Chapter 3</title>\n\
                     74:    <p>this is chapter 3 ...</p>\n\
                     75:   </chapter>\n\
                     76:   <chapter>\n\
                     77:    <title>Chapter 4</title>\n\
                     78:    <p>this is chapter 4 ...</p>\n\
                     79:   </chapter>\n\
                     80:   <chapter>\n\
                     81:    <title>Chapter 5</title>\n\
                     82:    <p>this is chapter 5 ...</p>\n\
                     83:   </chapter>\n\
1.2       daniel     84: </EXAMPLE>\n\
                     85: ";
1.1       daniel     86: 
1.22      veillard   87: void xmlXPAthDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
                     88:     int i;
                     89:     char shift[100];
                     90: 
                     91:     for (i = 0;((i < depth) && (i < 25));i++)
                     92:         shift[2 * i] = shift[2 * i + 1] = ' ';
                     93:     shift[2 * i] = shift[2 * i + 1] = 0;
1.20      veillard   94:     if (cur == NULL) {
1.22      veillard   95:        fprintf(output, shift);
1.20      veillard   96:        fprintf(output, "Node is NULL !\n");
                     97:        return;
                     98:         
                     99:     }
                    100: 
1.22      veillard  101:     if ((cur->type == XML_DOCUMENT_NODE) ||
                    102:             (cur->type == XML_HTML_DOCUMENT_NODE)) {
                    103:        fprintf(output, shift);
1.20      veillard  104:        fprintf(output, " /\n");
1.22      veillard  105:     } else if (cur->type == XML_ATTRIBUTE_NODE)
                    106:        xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
1.20      veillard  107:     else
1.22      veillard  108:        xmlDebugDumpOneNode(output, cur, depth);
1.20      veillard  109: }
                    110: 
1.22      veillard  111: void xmlXPAthDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
1.2       daniel    112:     int i;
1.22      veillard  113:     char shift[100];
                    114: 
                    115:     for (i = 0;((i < depth) && (i < 25));i++)
                    116:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    117:     shift[2 * i] = shift[2 * i + 1] = 0;
1.2       daniel    118: 
1.4       daniel    119:     if (cur == NULL) {
1.22      veillard  120:        fprintf(output, shift);
1.4       daniel    121:        fprintf(output, "NodeSet is NULL !\n");
                    122:        return;
                    123:         
                    124:     }
1.2       daniel    125: 
                    126:     fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
                    127:     for (i = 0;i < cur->nodeNr;i++) {
1.22      veillard  128:        fprintf(output, shift);
1.2       daniel    129:         fprintf(output, "%d", i + 1);
1.22      veillard  130:        xmlXPAthDebugDumpNode(output, cur->nodeTab[i], depth + 1);
1.20      veillard  131:     }
                    132: }
                    133: 
1.21      veillard  134: #if defined(LIBXML_XPTR_ENABLED)
1.22      veillard  135: void xmlXPAthDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth);
                    136: void xmlXPAthDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) {
1.20      veillard  137:     int i;
1.22      veillard  138:     char shift[100];
                    139: 
                    140:     for (i = 0;((i < depth) && (i < 25));i++)
                    141:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    142:     shift[2 * i] = shift[2 * i + 1] = 0;
1.20      veillard  143: 
                    144:     if (cur == NULL) {
1.22      veillard  145:        fprintf(output, shift);
1.20      veillard  146:        fprintf(output, "LocationSet is NULL !\n");
                    147:        return;
                    148:         
                    149:     }
                    150: 
                    151:     for (i = 0;i < cur->locNr;i++) {
1.22      veillard  152:        fprintf(output, shift);
                    153:         fprintf(output, "%d :\n", i + 1);
                    154:        xmlXPAthDebugDumpObject(output, cur->locTab[i], depth + 1);
1.2       daniel    155:     }
1.1       daniel    156: }
1.21      veillard  157: #endif
1.1       daniel    158: 
1.22      veillard  159: void xmlXPAthDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) {
                    160:     int i;
                    161:     char shift[100];
                    162: 
                    163:     for (i = 0;((i < depth) && (i < 25));i++)
                    164:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    165:     shift[2 * i] = shift[2 * i + 1] = 0;
                    166: 
                    167:     fprintf(output, shift);
                    168: 
1.1       daniel    169:     if (cur == NULL) {
                    170:         fprintf(output, "Object is empty (NULL)\n");
                    171:        return;
                    172:     }
                    173:     switch(cur->type) {
                    174:         case XPATH_UNDEFINED:
                    175:            fprintf(output, "Object is uninitialized\n");
                    176:            break;
                    177:         case XPATH_NODESET:
                    178:            fprintf(output, "Object is a Node Set :\n");
1.22      veillard  179:            xmlXPAthDebugDumpNodeSet(output, cur->nodesetval, depth);
1.1       daniel    180:            break;
                    181:         case XPATH_BOOLEAN:
                    182:            fprintf(output, "Object is a Boolean : ");
                    183:            if (cur->boolval) fprintf(output, "true\n");
                    184:            else fprintf(output, "false\n");
                    185:            break;
                    186:         case XPATH_NUMBER:
1.5       daniel    187:            fprintf(output, "Object is a number : %0g\n", cur->floatval);
1.1       daniel    188:            break;
                    189:         case XPATH_STRING:
                    190:            fprintf(output, "Object is a string : ");
                    191:            xmlDebugDumpString(output, cur->stringval);
1.5       daniel    192:            fprintf(output, "\n");
1.1       daniel    193:            break;
1.20      veillard  194:        case XPATH_POINT:
                    195:            fprintf(output, "Object is a point : index %d in node", cur->index);
1.22      veillard  196:            xmlXPAthDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
1.20      veillard  197:            fprintf(output, "\n");
                    198:            break;
                    199:        case XPATH_RANGE:
1.22      veillard  200:            fprintf(output, "Object is a range : from ");
1.20      veillard  201:            if (cur->index >= 0)
                    202:                fprintf(output, "index %d in ", cur->index);
                    203:            fprintf(output, "node");
1.22      veillard  204:            xmlXPAthDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
                    205:            fprintf(output, shift);
                    206:            fprintf(output, "                      to ");
1.20      veillard  207:            if (cur->index2 >= 0)
                    208:                fprintf(output, "index %d in ", cur->index2);
                    209:            fprintf(output, "node");
1.22      veillard  210:            xmlXPAthDebugDumpNode(output, (xmlNodePtr) cur->user2, depth + 1);
1.20      veillard  211:            fprintf(output, "\n");
1.22      veillard  212:            break;
1.20      veillard  213:        case XPATH_LOCATIONSET:
1.21      veillard  214: #if defined(LIBXML_XPTR_ENABLED)
1.22      veillard  215:            fprintf(output, "Object is a Location Set:\n");
                    216:            xmlXPAthDebugDumpLocationSet(output,
                    217:                    (xmlLocationSetPtr) cur->user, depth);
1.21      veillard  218: #endif
1.22      veillard  219:            break;
1.20      veillard  220:        case XPATH_USERS:
                    221:            fprintf(output, "Object is user defined\n");
1.22      veillard  222:            break;
1.1       daniel    223:     }
                    224: }
                    225: 
                    226: void testXPath(const char *str) {
                    227:     xmlXPathObjectPtr res;
                    228:     xmlXPathContextPtr ctxt;
                    229:     
1.19      veillard  230: #if defined(LIBXML_XPTR_ENABLED)
                    231:     if (xptr) {
                    232:        ctxt = xmlXPtrNewContext(document, NULL, NULL);
                    233:        res = xmlXPtrEval(BAD_CAST str, ctxt);
                    234:     } else {
                    235: #endif
                    236:        ctxt = xmlXPathNewContext(document);
                    237:        if (expr)
                    238:            res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
                    239:        else
                    240:            res = xmlXPathEval(BAD_CAST str, ctxt);
                    241: #if defined(LIBXML_XPTR_ENABLED)
                    242:     }
                    243: #endif
1.22      veillard  244:     xmlXPAthDebugDumpObject(stdout, res, 0);
1.1       daniel    245:     xmlXPathFreeObject(res);
1.6       veillard  246:     xmlXPathFreeContext(ctxt);
1.1       daniel    247: }
                    248: 
1.5       daniel    249: void testXPathFile(const char *filename) {
                    250:     FILE *input;
                    251:     char expr[5000];
1.22      veillard  252:     int len;
1.5       daniel    253: 
                    254:     input = fopen(filename, "r");
                    255:     if (input == NULL) {
                    256:         fprintf(stderr, "Cannot open %s for reading\n", filename);
                    257:        return;
                    258:     }
1.22      veillard  259:     while (fgets(expr, 4500, input) != NULL) {
                    260:        len = strlen(expr);
                    261:        len--;
                    262:        while ((len >= 0) && 
                    263:               ((expr[len] == '\n') || (expr[len] == '\t') ||
                    264:                (expr[len] == '\r') || (expr[len] == ' '))) len--;
                    265:        expr[len + 1] = 0;      
1.23      veillard  266:        if (len >= 0) {
                    267:            printf("\n========================\nExpression: %s\n", expr) ;
                    268:            testXPath(expr);
                    269:        }
1.5       daniel    270:     }
                    271: 
                    272:     fclose(input);
                    273: }
                    274: 
1.1       daniel    275: int main(int argc, char **argv) {
                    276:     int i;
                    277:     int strings = 0;
1.5       daniel    278:     int usefile = 0;
                    279:     char *filename = NULL;
1.1       daniel    280: 
                    281:     for (i = 1; i < argc ; i++) {
1.19      veillard  282: #if defined(LIBXML_XPTR_ENABLED)
                    283:        if ((!strcmp(argv[i], "-xptr")) || (!strcmp(argv[i], "--xptr")))
                    284:            xptr++;
                    285: #endif
1.1       daniel    286:        if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
                    287:            debug++;
1.18      veillard  288:        if ((!strcmp(argv[i], "-valid")) || (!strcmp(argv[i], "--valid")))
                    289:            valid++;
1.5       daniel    290:        if ((!strcmp(argv[i], "-expr")) || (!strcmp(argv[i], "--expr")))
                    291:            expr++;
                    292:        if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "--input")))
                    293:            filename = argv[++i];
                    294:        if ((!strcmp(argv[i], "-f")) || (!strcmp(argv[i], "--file")))
                    295:            usefile++;
                    296:     }
1.18      veillard  297:     if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
1.5       daniel    298:     if (document == NULL) {
                    299:         if (filename == NULL)
                    300:            document = xmlParseDoc(buffer);
                    301:        else
                    302:            document = xmlParseFile(filename);
1.1       daniel    303:     }
                    304:     for (i = 1; i < argc ; i++) {
1.5       daniel    305:        if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "--input"))) {
                    306:            i++; continue;
                    307:        }
1.1       daniel    308:        if (argv[i][0] != '-') {
1.5       daniel    309:            if (usefile)
                    310:                testXPathFile(argv[i]);
                    311:            else
                    312:                testXPath(argv[i]);
1.1       daniel    313:            strings ++;
                    314:        }
                    315:     }
                    316:     if (strings == 0) {
1.5       daniel    317:        printf("Usage : %s [--debug] [--copy] stringsorfiles ...\n",
1.1       daniel    318:               argv[0]);
                    319:        printf("\tParse the XPath strings and output the result of the parsing\n");
                    320:        printf("\t--debug : dump a debug version of the result\n");
1.18      veillard  321:        printf("\t--valid : switch on DTD support in the parser\n");
1.5       daniel    322:        printf("\t--expr : debug XPath expressions only\n");
                    323:        printf("\t--input filename : or\n");
                    324:        printf("\t-i filename      : read the document from filename\n");
                    325:        printf("\t--file : or\n");
                    326:        printf("\t-f     : read queries from files, args\n");
1.1       daniel    327:     }
1.15      daniel    328:     if (document != NULL) 
                    329:        xmlFreeDoc(document);
                    330:     xmlCleanupParser();
                    331:     xmlMemoryDump();
1.1       daniel    332: 
                    333:     return(0);
                    334: }
1.17      daniel    335: #else
                    336: #include <stdio.h>
                    337: int main(int argc, char **argv) {
                    338:     printf("%s : XPath/Debug support not compiled in\n", argv[0]);
                    339:     return(0);
                    340: }
                    341: #endif /* LIBXML_XPATH_ENABLED */

Webmaster