/* If the result has a root element, copy it in place of the root
* element of the original document to preserve the original DTD. */
if ((new = xmlDocGetRootElement(doc))) {
xmlNodePtr old;
old = xmlDocSetRootElement(src, xmlCopyNode(new, 1));
xmlFreeNode(old);
/* Otherwise, copy the whole doc to keep non-XML results. */
} else {
xmlFreeDoc(src);
src = xmlCopyDoc(doc, 1);
}
xmlFreeDoc(doc);
return src;
}
/* Apply stylesheets to a doc. */
static xmlDocPtr transform_doc(xmlDocPtr doc, xmlNodePtr stylesheets)
{
xmlNodePtr cur;
for (cur = stylesheets->children; cur; cur = cur->next) {
xmlDocPtr res;
xsltStylesheetPtr style;
const char **params;
/* Save a document using the output settings of the specified stylesheet. */
static void save_doc(xmlDocPtr doc, const char *path, xsltStylesheetPtr style)
{
if (xmlStrcmp(style->method, BAD_CAST "text") == 0) {
FILE *f;
if (strcmp(path, "-") == 0) {
f = stdout;
} else {
f = fopen(path, "w");
}
if (!f) {
fprintf(stderr, E_FILE_NO_WRITE, path, strerror(errno));
exit(EXIT_OS_ERROR);
}
/* Use the output settings of the last stylesheet to determine how to
* save the end result. */
if (stylesheets != NULL && stylesheets->last != NULL) {
last = (xsltStylesheetPtr) stylesheets->last->doc;
} else if (xml_stylesheets != NULL && xml_stylesheets->last != NULL) {
last = (xsltStylesheetPtr) xml_stylesheets->last->doc;
}
if (last != NULL) {
if (overwrite) {
save_doc(doc, path, last);
} else {
save_doc(doc, out, last);
}
/* If no stylesheets are specified, save as-is. */
} else {
if (overwrite) {
save_xml_doc(doc, path);
} else {
save_xml_doc(doc, out);
}
}
if (use_xml_stylesheets) {
free_stylesheets(xml_stylesheets);
}
xmlFreeDoc(doc);
}
/* Apply stylesheets to a list of files. */
static void transform_list(const char *path, xmlNodePtr stylesheets, const char *out, bool overwrite)
{
FILE *f;
char line[PATH_MAX];
if (path) {
if (!(f = fopen(path, "r"))) {
if (verbosity >= NORMAL) {
fprintf(stderr, E_BAD_LIST, path, strerror(errno));
}
return;
}
} else {
f = stdin;
}
/* Combine a single file into the combined document. */
static void combine_file(xmlNodePtr combined, const char *path)
{
xmlDocPtr doc = read_xml_doc(path);
xmlAddChild(combined, xmlCopyNode(xmlDocGetRootElement(doc), 1));
xmlFreeDoc(doc);
}
/* Combine a list of files into the combined document. */
static void combine_file_list(xmlNodePtr combined, const char *path)
{
FILE *f;
char line[PATH_MAX];
if (path) {
if (!(f = fopen(path, "r"))) {
if (verbosity >= NORMAL) {
fprintf(stderr, E_BAD_LIST, path, strerror(errno));
}
return;
}
} else {
f = stdin;
}
while (fgets(line, PATH_MAX, f)) {
strtok(line, "\t\r\n");
combine_file(combined, line);
}
/* Combine all input files into a single document. */
if (optind < argc) {
int i;
for (i = optind; i < argc; ++i) {
if (islist) {
combine_file_list(combined, argv[i]);
} else {
combine_file(combined, argv[i]);
}
}
} else if (islist) {
combine_file_list(combined, NULL);
} else {
combine_file(combined, "-");
}
doc = transform_doc(doc, stylesheets);
/* Use the output settings of the last stylesheet to determine how to
* save the end result. */
if (stylesheets->last) {
xsltStylesheetPtr last;
last = (xsltStylesheetPtr) stylesheets->last->doc;
save_doc(doc, out, last);
/* If no stylesheets were specified, save as-is. */
} else {
save_xml_doc(doc, out);
}
xmlFreeDoc(doc);
}
/* Show help/usage message. */
static void show_help(void)
{
puts("Usage: " PROG_NAME " [-s <stylesheet> [-p <name>=<value> ...] ...] [-o <file>] [-cdfilqSvh?] [<file>...]");
puts("");
puts("Options:");
puts(" -c, --combine Combine input files into a single document.");
puts(" -d, --preserve-dtd Preserve the original DTD.");
puts(" -f, --overwrite Overwrite input files.");
puts(" -h, -?, --help Show usage message.");
puts(" -i, --identity Include identity template in stylesheets.");
puts(" -l, --list Treat input as list of files.");
puts(" -o, --out <file> Output result of transformation to <path>.");
puts(" -p, --param <name>=<value> Pass parameters to stylesheets.");
puts(" -q, --quiet Quiet mode.");
puts(" -S, --xml-stylesheets Apply associated stylesheets.");
puts(" -s, --stylesheet <stylesheet> Apply XSLT stylesheet to XML documents.");
puts(" -v, --verbose Verbose output.");
puts(" --version Show version information.");
puts(" <file> XML documents to apply transformations to.");
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, libxslt %s and libexslt %s\n",
xmlParserVersion, xsltEngineVersion, exsltLibraryVersion);
}