void xpath::init_raw_(const std::string& str) { // Compile the XPath expression. xmlXPathCompExpr* px = xmlXPathCompile(detail::to_xml_chars(str.c_str())); if (px == 0) { std::string what = "fail to compile XPath expression: " + str; throw xpath_error(what); } // Free the underlying XPath expression object as necessary. if (raw_ != 0) { xmlXPathFreeCompExpr(raw_); raw_ = 0; } // Reset raw. raw_ = px; }
int main(int argc, char **argv) { #else int xpath_locator(int argc, char **argv) { #endif if (argc < 2) { fprintf(stderr, "Need to specify an input filename.\n" "Usage: xpath_locator file.xml xpath1 xpath2 ...\n"); exit(1); } char *xml_filename = argv[1]; num_xpaths = argc - 2; xpath_finders = (XPathFinder *) mmalloc(num_xpaths * sizeof(XPathFinder)); for (int xpath_num = 0; xpath_num < num_xpaths; ++xpath_num) { xmlChar *xpath_expr = (xmlChar *) argv[xpath_num + 2]; XPathFinder *xpath_finder = &xpath_finders[xpath_num]; xpath_finder->original = new_string(xpath_expr); xpath_finder->current_level = 0; xpath_finder->line_number = 0; xpath_finder->column_number = 0; escape_uri_slashes(xpath_expr, TRUE); int num_segs = xpath_finder->num_segs = count_chars(xpath_expr, '/'); XPathSegFinder *seg_finders = (XPathSegFinder *) mmalloc(num_segs * sizeof(XPathSegFinder)); xpath_finder->seg_finders = seg_finders; /* Extract each XPath segment */ xmlChar *seg = xstrtok(xpath_expr, "/"); int seg_num = 0; while (seg != NULL) { XPathSegFinder *seg_finder = &seg_finders[seg_num]; seg_finder->count = 0; escape_uri_slashes(seg, FALSE); seg_finder->original = new_string(seg); // Get the element local name xmlChar *lns = starts_with(seg, (const xmlChar *) "*:") ? seg + 2 : seg; const xmlChar *bracket = xstrchr(seg, '['); if (!bracket) xpath_error(xpath_num, xpath_finder, seg_num, "No bracket found"); int local_name_len = bracket - lns; xmlChar *local_name = seg_finder->local_name = new_string_n(lns, local_name_len); if (starts_with(bracket + 1, (const xmlChar *) "namespace-uri()=")) { const xmlChar *ns_start = bracket + 18; const xmlChar *ns_end = xstrchr(ns_start, '\''); if (!ns_end) xpath_error(xpath_num, xpath_finder, seg_num, "No end to the namespace URI"); seg_finder->namespace_uri = new_string_n(ns_start, ns_end - ns_start); bracket = xstrchr(ns_end, '['); if (!bracket) xpath_error(xpath_num, xpath_finder, seg_num, "No position found"); } else { seg_finder->namespace_uri = NULL; } const xmlChar *pos_start = bracket + 1; const xmlChar *pos_end = xstrchr(pos_start, ']'); if (!pos_end) xpath_error(xpath_num, xpath_finder, seg_num, "No closing bracket found"); size_t pos_str_len = pos_end - pos_start; char pos_str[10]; strncpy(pos_str, (const char *) pos_start, pos_str_len); pos_str[pos_str_len] = 0; seg_finder->position = strtol(pos_str, NULL, 10); if (seg_finder->position <= 0) xpath_error(xpath_num, xpath_finder, seg_num, "Bad position argument"); seg = xstrtok(NULL, "/"); seg_num++; } } // Initialize default handler structure for SAX 2 xmlSAXVersion(handlers, 2); handlers->startElementNs = my_startElementNs; handlers->endElementNs = my_endElementNs; parser_level = 0; // [c] parser_level is safe int res = xmlSAXUserParseFile(handlers, NULL, xml_filename); // Output the results for (int xpath_num = 0; xpath_num < num_xpaths; ++xpath_num) { XPathFinder *xpath_finder = &xpath_finders[xpath_num]; printf("%d:%d\n", xpath_finder->line_number, xpath_finder->column_number); } for (int xpath_num = 0; xpath_num < num_xpaths; ++xpath_num) { XPathFinder *xpath_finder = &xpath_finders[xpath_num]; int num_segs = xpath_finder->num_segs; XPathSegFinder *seg_finders = xpath_finder->seg_finders; for (int seg_num = 0; seg_num < num_segs; ++seg_num) { XPathSegFinder *seg_finder = &seg_finders[seg_num]; ffree(seg_finder->original); ffree(seg_finder->local_name); ffree(seg_finder->namespace_uri); } ffree(xpath_finder->seg_finders); ffree(xpath_finder->original); } ffree(xpath_finders); return 0; }