Return to xpath1.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / doc / examples |
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