Annotation of embedaddon/libxml2/doc/examples/xpath1.c, revision 1.1.1.1

1.1       misho       1: /** 
                      2:  * section:    XPath
                      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.
                     10:  */
                     11: #include <stdlib.h>
                     12: #include <stdio.h>
                     13: #include <string.h>
                     14: #include <assert.h>
                     15: 
                     16: #include <libxml/tree.h>
                     17: #include <libxml/parser.h>
                     18: #include <libxml/xpath.h>
                     19: #include <libxml/xpathInternals.h>
                     20: 
                     21: #if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_SAX1_ENABLED)
                     22: 
                     23: 
                     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);
                     28: 
                     29: int 
                     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");
                     34:        usage(argv[0]);
                     35:        return(-1);
                     36:     } 
                     37:     
                     38:     /* Init libxml */     
                     39:     xmlInitParser();
                     40:     LIBXML_TEST_VERSION
                     41: 
                     42:     /* Do the main job */
                     43:     if(execute_xpath_expression(argv[1], BAD_CAST argv[2], (argc > 3) ? BAD_CAST argv[3] : NULL) < 0) {
                     44:        usage(argv[0]);
                     45:        return(-1);
                     46:     }
                     47: 
                     48:     /* Shutdown libxml */
                     49:     xmlCleanupParser();
                     50:     
                     51:     /*
                     52:      * this is to debug memory for regression tests
                     53:      */
                     54:     xmlMemoryDump();
                     55:     return 0;
                     56: }
                     57: 
                     58: /**
                     59:  * usage:
                     60:  * @name:              the program name.
                     61:  *
                     62:  * Prints usage information.
                     63:  */
                     64: static void 
                     65: usage(const char *name) {
                     66:     assert(name);
                     67:     
                     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");
                     71: }
                     72: 
                     73: /**
                     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.
                     79:  *
                     80:  * Parses input XML file, evaluates XPath expression and prints results.
                     81:  *
                     82:  * Returns 0 on success and a negative value otherwise.
                     83:  */
                     84: int 
                     85: execute_xpath_expression(const char* filename, const xmlChar* xpathExpr, const xmlChar* nsList) {
                     86:     xmlDocPtr doc;
                     87:     xmlXPathContextPtr xpathCtx; 
                     88:     xmlXPathObjectPtr xpathObj; 
                     89:     
                     90:     assert(filename);
                     91:     assert(xpathExpr);
                     92: 
                     93:     /* Load XML document */
                     94:     doc = xmlParseFile(filename);
                     95:     if (doc == NULL) {
                     96:        fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
                     97:        return(-1);
                     98:     }
                     99: 
                    100:     /* Create xpath evaluation context */
                    101:     xpathCtx = xmlXPathNewContext(doc);
                    102:     if(xpathCtx == NULL) {
                    103:         fprintf(stderr,"Error: unable to create new XPath context\n");
                    104:         xmlFreeDoc(doc); 
                    105:         return(-1);
                    106:     }
                    107:     
                    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); 
                    112:         xmlFreeDoc(doc); 
                    113:         return(-1);
                    114:     }
                    115: 
                    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); 
                    121:         xmlFreeDoc(doc); 
                    122:         return(-1);
                    123:     }
                    124: 
                    125:     /* Print results */
                    126:     print_xpath_nodes(xpathObj->nodesetval, stdout);
                    127: 
                    128:     /* Cleanup */
                    129:     xmlXPathFreeObject(xpathObj);
                    130:     xmlXPathFreeContext(xpathCtx); 
                    131:     xmlFreeDoc(doc); 
                    132:     
                    133:     return(0);
                    134: }
                    135: 
                    136: /**
                    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.
                    141:  *
                    142:  * Registers namespaces from @nsList in @xpathCtx.
                    143:  *
                    144:  * Returns 0 on success and a negative value otherwise.
                    145:  */
                    146: int 
                    147: register_namespaces(xmlXPathContextPtr xpathCtx, const xmlChar* nsList) {
                    148:     xmlChar* nsListDup;
                    149:     xmlChar* prefix;
                    150:     xmlChar* href;
                    151:     xmlChar* next;
                    152:     
                    153:     assert(xpathCtx);
                    154:     assert(nsList);
                    155: 
                    156:     nsListDup = xmlStrdup(nsList);
                    157:     if(nsListDup == NULL) {
                    158:        fprintf(stderr, "Error: unable to strdup namespaces list\n");
                    159:        return(-1);     
                    160:     }
                    161:     
                    162:     next = nsListDup; 
                    163:     while(next != NULL) {
                    164:        /* skip spaces */
                    165:        while((*next) == ' ') next++;
                    166:        if((*next) == '\0') break;
                    167: 
                    168:        /* find prefix */
                    169:        prefix = next;
                    170:        next = (xmlChar*)xmlStrchr(next, '=');
                    171:        if(next == NULL) {
                    172:            fprintf(stderr,"Error: invalid namespaces list format\n");
                    173:            xmlFree(nsListDup);
                    174:            return(-1); 
                    175:        }
                    176:        *(next++) = '\0';       
                    177:        
                    178:        /* find href */
                    179:        href = next;
                    180:        next = (xmlChar*)xmlStrchr(next, ' ');
                    181:        if(next != NULL) {
                    182:            *(next++) = '\0';   
                    183:        }
                    184: 
                    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);
                    188:            xmlFree(nsListDup);
                    189:            return(-1); 
                    190:        }
                    191:     }
                    192:     
                    193:     xmlFree(nsListDup);
                    194:     return(0);
                    195: }
                    196: 
                    197: /**
                    198:  * print_xpath_nodes:
                    199:  * @nodes:             the nodes set.
                    200:  * @output:            the output file handle.
                    201:  *
                    202:  * Prints the @nodes content to @output.
                    203:  */
                    204: void
                    205: print_xpath_nodes(xmlNodeSetPtr nodes, FILE* output) {
                    206:     xmlNodePtr cur;
                    207:     int size;
                    208:     int i;
                    209:     
                    210:     assert(output);
                    211:     size = (nodes) ? nodes->nodeNr : 0;
                    212:     
                    213:     fprintf(output, "Result (%d nodes):\n", size);
                    214:     for(i = 0; i < size; ++i) {
                    215:        assert(nodes->nodeTab[i]);
                    216:        
                    217:        if(nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
                    218:            xmlNsPtr ns;
                    219:            
                    220:            ns = (xmlNsPtr)nodes->nodeTab[i];
                    221:            cur = (xmlNodePtr)ns->next;
                    222:            if(cur->ns) { 
                    223:                fprintf(output, "= namespace \"%s\"=\"%s\" for node %s:%s\n", 
                    224:                    ns->prefix, ns->href, cur->ns->href, cur->name);
                    225:            } else {
                    226:                fprintf(output, "= namespace \"%s\"=\"%s\" for node %s\n", 
                    227:                    ns->prefix, ns->href, cur->name);
                    228:            }
                    229:        } else if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
                    230:            cur = nodes->nodeTab[i];        
                    231:            if(cur->ns) { 
                    232:                fprintf(output, "= element node \"%s:%s\"\n", 
                    233:                    cur->ns->href, cur->name);
                    234:            } else {
                    235:                fprintf(output, "= element node \"%s\"\n", 
                    236:                    cur->name);
                    237:            }
                    238:        } else {
                    239:            cur = nodes->nodeTab[i];    
                    240:            fprintf(output, "= node \"%s\": type %d\n", cur->name, cur->type);
                    241:        }
                    242:     }
                    243: }
                    244: 
                    245: #else
                    246: int main(void) {
                    247:     fprintf(stderr, "XPath support not compiled in\n");
                    248:     exit(1);
                    249: }
                    250: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>