summaryrefslogtreecommitdiffstats
path: root/gxpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gxpm.c')
-rw-r--r--gxpm.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/gxpm.c b/gxpm.c
new file mode 100644
index 0000000..b384530
--- /dev/null
+++ b/gxpm.c
@@ -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;
+}
+