diff options
Diffstat (limited to 'gxpm.c')
-rw-r--r-- | gxpm.c | 136 |
1 files changed, 136 insertions, 0 deletions
@@ -0,0 +1,136 @@ +/* + * gxpm.c -- Simple XPath Merge Util + * + * Copyright © 2006-2007 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions of the + * GNU General Public License v.2. This program is distributed in the hope + * that it will be useful, but WITHOUT ANY WARRANTY expressed or implied, + * including the implied warranties of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat + * trademarks that are incorporated in the source code or documentation are not + * subject to the GNU General Public License and may only be used or replicated + * with the express permission of Red Hat, Inc. + * + * Red Hat Author(s): Nathan Straz <nstraz@redhat.com> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <getopt.h> +#include <string.h> +#include <ctype.h> + +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <libxml/xpath.h> +#include <libxml/xpathInternals.h> +#include <libxml/xinclude.h> + +#include "gxp-int.h" + +static void usage(const char *pname); +static int gxpm(char *fn, const char *xpath_query, const char *prefix, xmlDocPtr snip); + +int +main(int argc, char **argv) +{ + xmlDocPtr snip; + char *xpath_query = NULL; + char *prefix = NULL; + int c; + + while ((c = getopt(argc, argv, "+p:h")) != -1) { + switch (c) { + case 'p': + prefix = strdup(optarg); + break; + case 'h': + case '?': + usage(argv[0]); + exit(2); + break; + } + } + xpath_query = argv[optind]; + if (!xpath_query) { + fprintf(stderr, "Missing XPath Query\n"); + usage(argv[0]); + exit(2); + } + + if (!(snip = xmlReadFd(fileno(stdin), NULL, NULL, 0))) { + fprintf(stderr, "Failed to parse XML snippet on standard input\n"); + exit(1); + } + + optind++; + if (!argv[optind]) { + /* No files given, filter stdin to stdout */ + gxpm("-", xpath_query, prefix, snip); + } else { + /* Rest of the args are the files to change */ +#if 0 + if (((argc - optind) > 1) + && (!gxpp_opts.omitfileprefix)) gxpp_opts.addfileprefix = 1; +#endif + for (c = optind; c < argc; c++) { + /* Make sure we can write to the file */ + gxpm(argv[c], xpath_query, prefix, snip); + } + } + xmlFreeDoc(snip); + return 0; +} + +static int +gxpm(char *fn, const char *xpath_query, const char *prefix, xmlDocPtr snip) +{ + xmlDocPtr doc; + xmlXPathContextPtr ctx; + xmlXPathObjectPtr obj; + int i; + + if (!(doc = xmlParseFile(fn))) { + fprintf(stderr, "Failed to parse XML file\n"); + exit(1); + } + /* xmlXIncludeProcess(doc); */ + ctx = generate_context(doc, prefix); + obj = xmlXPathEvalExpression((xmlChar *)xpath_query, ctx); + if (!obj) { + fprintf(stderr, "XPath expression '%s' did not match in '%s'\n", + xpath_query, fn); + exit(1); + } + if (obj->type != XPATH_NODESET) { + fprintf(stderr, "XPath expression '%s' did not match a nodeset.\n", xpath_query); + exit(1); + } + for (i = 0; i < obj->nodesetval->nodeNr; i++) { + xmlAddChild(obj->nodesetval->nodeTab[i], xmlCopyNode(xmlDocGetRootElement(snip), 1)); + } + + xmlXPathFreeObject(obj); + xmlXPathFreeContext(ctx); + xmlSaveFile(fn, doc); + + xmlFreeDoc(doc); + + return 0; +} + + +static void +usage(const char *pname) +{ + fprintf(stderr,"%s [OPTION]... XPATH [FILE]... < XML\n", pname); + fprintf(stderr,"Options:\n" + "-p prefix Set prefix for default namespace\n"); + return; +} + |