#define PROG_NAME "xml-trim"
#define VERSION "3.5.1"
#define is_space(c) isspace((unsigned char) c)
/* Remove whitespace on left end of string. */
static char *strltrm(char *dst, const char *src)
{
int start;
for (start = 0; is_space(src[start]); ++start);
sprintf(dst, "%s", src + start);
return dst;
}
/* Remove whitespace on right end of string. */
static char *strrtrm(char *dst, const char *src)
{
int len, end;
len = strlen(src);
for (end = len - 1; is_space(src[end]); --end);
sprintf(dst, "%.*s", end + 1, src);
return dst;
}
/* Normalize space by replacing all sequences of whitespace characters with a
* single space.
*/
static char *strnorm(char *dst, const char *src)
{
int i, j;
j = 0;
for (i = 0; src[i]; ++i) {
if (is_space(src[i])) {
dst[j] = ' ';
while (is_space(src[i + 1])) {
++i;
}
} else {
dst[j] = src[i];
}
++j;
}
return dst;
}
/* Register an XML namespace with the XPath context. */
static void register_ns(xmlXPathContextPtr ctx, char *optarg)
{
char *prefix, *uri;
prefix = strtok(optarg, "=");
uri = strtok(NULL, "");
for (cur = ns->children; cur; cur = cur->next) {
xmlChar *n;
n = xmlNodeGetContent(cur);
register_ns(ctx, (char *) n);
xmlFree(n);
}
for (cur = elems->children; cur; cur = cur->next) {
xmlChar *xpath;
xmlXPathObjectPtr obj;
xmlChar *e;
e = xmlNodeGetContent(cur);
/* If the element specifier contains a /, treat it like a
* literal XPath expression.
*
* Otherwise, match all elements with the same name at any
* position.
*/
if (xmlStrchr(e, '/')) {
xpath = xmlStrdup(e);
} else {
xpath = xmlStrdup(BAD_CAST "//");
xpath = xmlStrcat(xpath, e);
}
xmlFree(e);
obj = xmlXPathEvalExpression(xpath, ctx);
xmlFree(xpath);
if (!xmlXPathNodeSetIsEmpty(obj->nodesetval)) {
trim_nodes(obj->nodesetval, normalize);
}
/* Show usage message. */
static void show_help(void)
{
puts("Usage: " PROG_NAME " [-e <elem> ...] [-N <ns=URL> ...] [-fnh?] [<src>...]");
puts("");
puts("Options:");
puts(" -e, --element <elem> Element to trim space on.");
puts(" -f, --overwrite Overwrite input files.");
puts(" -h, -?, --help Show usage message.");
puts(" -N, --namespace <ns=URL> Register a namespace.");
puts(" -n, --normalize Normalize space as well as trim.");
puts(" --version Show version information.");
puts(" <src> XML file to trim.");
LIBXML2_PARSE_LONGOPT_HELP
}
/* Show version information. */
static void show_version(void)
{
printf("%s (xml-utils) %s\n", PROG_NAME, VERSION);
printf("Using libxml %s\n", xmlParserVersion);
}
int main(int argc, char **argv)
{
int i;
xmlNodePtr ns, elems;
bool normalize = false;
bool overwrite = false;