..
/
download
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
#include <libgen.h>
#include <sys/stat.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxslt/transform.h>
#include "s1kd_tools.h"
#include "xsl.h"
#define PROG_NAME "s1kd-flatten"
#define VERSION "3.4.1"
#define ERR_PREFIX PROG_NAME ": ERROR: "
#define WRN_PREFIX PROG_NAME ": WARNING: "
#define INF_PREFIX PROG_NAME ": INFO: "
#define E_BAD_PM ERR_PREFIX "Bad publication module: %s\n"
#define E_ENCODING_ERROR ERR_PREFIX "An encoding error occurred: %s (%d)\n"
#define E_BAD_LIST ERR_PREFIX "Could not read list: %s\n"
#define W_MISSING_REF WRN_PREFIX "Could not read referenced object: %s\n"
#define I_INCLUDE INF_PREFIX "Including %s...\n"
#define I_FOUND INF_PREFIX "Found %s\n"
#define I_REMOVE INF_PREFIX "Removing %s...\n"
#define I_SEARCH INF_PREFIX "Searching for %s in '%s' ...\n"
#define I_REMDUPS INF_PREFIX "Removing duplicate references...\n"
#define EXIT_BAD_PM 1
#define EXIT_ENCODING_ERROR 2
#define ENCODING_ERROR {\
fprintf(stderr, "An encoding error occurred: %s (%d)\n", __FILE__, __LINE__);\
exit(EXIT_ENCODING_ERROR);\
}
static int xinclude = 0;
static int no_issue = 0;
static int ignore_iss = 0;
static int use_pub_fmt = 0;
static xmlDocPtr pub_doc = NULL;
static xmlNodePtr pub;
static xmlNodePtr search_paths;
static char *search_dir;
static int flatten_ref = 1;
static int flatten_container = 0;
static int recursive = 0;
static int recursive_search = 0;
static int remove_unresolved = 0;
static int only_pm_refs = 0;
static enum verbosity { QUIET, NORMAL, VERBOSE, DEBUG } verbosity = NORMAL;
static void show_help(void)
{
puts("Usage: " PROG_NAME " [-d <dir>] [-I <path>] [-cDfilmNPpqRruvxh?] <pubmodule> [<dmodule>...]");
puts("");
puts("Options:");
puts(" -c, --containers Flatten referenced container data modules.");
puts(" -D, --remove Remove unresolved references.");
puts(" -d, --dir <dir> Directory to start search in.");
puts(" -f, --overwrite Overwrite publication module.");
puts(" -h, -?, --help Show help/usage message.");
puts(" -I, --include <path> Search <path> for referenced objects.");
puts(" -i, --ignore-issue Always match the latest issue of an object found.");
puts(" -l, --list Treat input as a list of objects.");
puts(" -m, --modify Modiy references without flattening them.");
puts(" -N, --omit-issue Assume issue/inwork numbers are omitted.");
puts(" -P, --only-pm-refs Only flatten PM refs.");
puts(" -p, --simple Output a simple, flat XML file.");
puts(" -q, --quiet Quiet mode.");
puts(" -R, --recursively Recursively flatten referenced PMs.");
puts(" -r, --recursive Search directories recursively.");
puts(" -u, --unique Remove duplicate references.");
puts(" -v, --verbose Verbose output.");
puts(" -x, --use-xinclude Use XInclude references.");
puts(" --version Show version information.");
LIBXML2_PARSE_LONGOPT_HELP
}
static void show_version(void)
{
printf("%s (s1kd-tools) %s\n", PROG_NAME, VERSION);
printf("Using libxml %s and libxslt %s\n", xmlParserVersion, xsltEngineVersion);
}
static xmlNodePtr find_child(xmlNodePtr parent, const char *child_name)
{
xmlNodePtr cur;
for (cur = parent->children; cur; cur = cur->next) {
if (strcmp((char *) cur->name, child_name) == 0) {
return cur;
}
}
return NULL;
}
static xmlNodePtr first_xpath_node(xmlDocPtr doc, xmlNodePtr node, const char *expr)
{
xmlXPathContextPtr ctx;
xmlXPathObjectPtr obj;
xmlNodePtr first;
ctx = xmlXPathNewContext(doc ? doc : node->doc);
ctx->node = node;
obj = xmlXPathEvalExpression(BAD_CAST expr, ctx);
first = xmlXPathNodeSetIsEmpty(obj->nodesetval) ? NULL : obj->nodesetval->nodeTab[0];
xmlXPathFreeObject(obj);
xmlXPathFreeContext(ctx);
return first;
}
static char *first_xpath_string(xmlDocPtr doc, xmlNodePtr node, const char *expr)
{
return (char *) xmlNodeGetContent(first_xpath_node(doc, node, expr));
}
static void flatten_pm_entry(xmlNodePtr pm_entry, xmlNsPtr xiNs);
static void flatten_pm_ref(xmlNodePtr pm_ref, xmlNsPtr xiNs)
{
xmlNodePtr pm_code;
xmlNodePtr issue_info;
xmlNodePtr language;
char *model_ident_code;
char *pm_issuer;
char *pm_number;
char *pm_volume;
char *issue_number = NULL;
char *in_work = NULL;
char *language_iso_code = NULL;
char *country_iso_code = NULL;
char pmc[256];
char pm_fname[PATH_MAX];
char pm_fname_temp[PATH_MAX];
char fs_pm_fname[PATH_MAX] = "";
xmlNodePtr xi;
xmlDocPtr doc;
xmlNodePtr pm;
bool found = false;
xmlNodePtr cur;
/* Skip PM refs if they do not need to be processed. */
if (!(flatten_ref || remove_unresolved || recursive)) {
return;
}
pm_code = first_xpath_node(NULL, pm_ref, ".//pmCode|.//pmc");
issue_info = ignore_iss ? NULL : first_xpath_node(NULL, pm_ref, ".//issueInfo|.//issno");
language = first_xpath_node(NULL, pm_ref, ".//language");
model_ident_code = first_xpath_string(NULL, pm_code, "@modelIdentCode|modelic");
pm_issuer = first_xpath_string(NULL, pm_code, "@pmIssuer|pmissuer");
pm_number = first_xpath_string(NULL, pm_code, "@pmNumber|pmnumber");
pm_volume = first_xpath_string(NULL, pm_code, "@pmVolume|pmvolume");
snprintf(pmc, 256, "%s-%s-%s-%s",
model_ident_code,
pm_issuer,
pm_number,
pm_volume);
snprintf(pm_fname, PATH_MAX, "PMC-%s", pmc);
if (!no_issue) {
strcpy(pm_fname_temp, pm_fname);
if (issue_info) {
issue_number = first_xpath_string(NULL, issue_info, "@issueNumber|@issno");
in_work = first_xpath_string(NULL, issue_info, "@inWork|@inwork");
if (snprintf(pm_fname, PATH_MAX, "%s_%s-%s", pm_fname_temp, issue_number, in_work ? in_work : "00") < 0) {
ENCODING_ERROR
}
} else if (language) {
if (snprintf(pm_fname, PATH_MAX, "%s_\?\?\?-\?\?", pm_fname_temp) < 0) {
ENCODING_ERROR
}
}
}
if (language) {
int i;
language_iso_code = first_xpath_string(NULL, language, "@languageIsoCode|@language");
country_iso_code = first_xpath_string(NULL, language, "@countryIsoCode|@country");
for (i = 0; language_iso_code[i]; ++i)
language_iso_code[i] = toupper(language_iso_code[i]);
strcpy(pm_fname_temp, pm_fname);
if (snprintf(pm_fname, PATH_MAX, "%s_%s-%s", pm_fname_temp, language_iso_code, country_iso_code) < 0) {
ENCODING_ERROR
}
}
xmlFree(model_ident_code);
xmlFree(pm_issuer);
xmlFree(pm_number);
xmlFree(pm_volume);
xmlFree(issue_number);
xmlFree(in_work);
xmlFree(language_iso_code);
xmlFree(country_iso_code);
for (cur = search_paths->children; cur && !found; cur = cur->next) {
char *path;
path = (char *) xmlNodeGetContent(cur);
if (verbosity >= DEBUG) {
fprintf(stderr, I_SEARCH, pm_fname, path);
}
if (find_csdb_object(fs_pm_fname, path, pm_fname, is_pm, recursive_search)) {
if (verbosity >= DEBUG) {
fprintf(stderr, I_FOUND, fs_pm_fname);
}
found = true;
if (recursive) {
xmlDocPtr subpm;
xmlNodePtr content;
if (verbosity >= VERBOSE) {
fprintf(stderr, I_INCLUDE, fs_pm_fname);
}
subpm = read_xml_doc(fs_pm_fname);
content = first_xpath_node(subpm, NULL, "//content");
if (content) {
xmlNodePtr c;
flatten_pm_entry(content, xiNs);
for (c = content->last; c; c = c->prev) {
if (xmlStrcmp(c->name, BAD_CAST "pmEntry") != 0) {
continue;
}
xmlAddNextSibling(pm_ref, xmlCopyNode(c, 1));
}
}
xmlFreeDoc(subpm);
} else if (flatten_ref) {
if (verbosity >= VERBOSE) {
fprintf(stderr, I_INCLUDE, fs_pm_fname);
}
if (xinclude) {
xi = xmlNewNode(xiNs, BAD_CAST "include");
xmlSetProp(xi, BAD_CAST "href", BAD_CAST fs_pm_fname);
if (use_pub_fmt) {
xi = xmlAddChild(pub, xi);
} else {
xi = xmlAddPrevSibling(pm_ref, xi);
}
} else {
doc = read_xml_doc(fs_pm_fname);
pm = xmlDocGetRootElement(doc);
xmlAddPrevSibling(pm_ref, xmlCopyNode(pm, 1));
xmlFreeDoc(doc);
}
}
} else if (remove_unresolved) {
if (verbosity >= VERBOSE) {
fprintf(stderr, I_REMOVE, pm_fname);
}
} else {
if (verbosity >= NORMAL) {
fprintf(stderr, W_MISSING_REF, pm_fname);
}
}
xmlFree(path);
}
if ((found && (flatten_ref || recursive)) || (!found && remove_unresolved)) {
xmlUnlinkNode(pm_ref);
xmlFreeNode(pm_ref);
}
}
static void flatten_dm_ref(xmlNodePtr dm_ref, xmlNsPtr xiNs)
{
xmlNodePtr dm_code;
xmlNodePtr issue_info;
xmlNodePtr language;
char *model_ident_code;
char *system_diff_code;
char *system_code;
char *sub_system_code;
char *sub_sub_system_code;
char *assy_code;
char *disassy_code;
char *disassy_code_variant;
char *info_code;
char *info_code_variant;
char *item_location_code;
char *issue_number = NULL;
char *in_work = NULL;
char *language_iso_code = NULL;
char *country_iso_code = NULL;
char dmc[256];
char dm_fname[PATH_MAX];
char dm_fname_temp[PATH_MAX];
char fs_dm_fname[PATH_MAX] = "";
xmlNodePtr xi;
xmlDocPtr doc;
xmlNodePtr dmodule;
bool found = false;
xmlNodePtr cur;
/* Skip DM refs if they do not need to be processed. */
if (only_pm_refs || !(flatten_ref || remove_unresolved || flatten_container)) {
return;
}
dm_code = first_xpath_node(NULL, dm_ref, ".//dmCode|.//avee");
issue_info = ignore_iss ? NULL : first_xpath_node(NULL, dm_ref, ".//issueInfo|.//issno");
language = first_xpath_node(NULL, dm_ref, ".//language");
model_ident_code = first_xpath_string(NULL, dm_code, "@modelIdentCode|modelic");
system_diff_code = first_xpath_string(NULL, dm_code, "@systemDiffCode|sdc");
system_code = first_xpath_string(NULL, dm_code, "@systemCode|chapnum");
sub_system_code = first_xpath_string(NULL, dm_code, "@subSystemCode|section");
sub_sub_system_code = first_xpath_string(NULL, dm_code, "@subSubSystemCode|subsect");
assy_code = first_xpath_string(NULL, dm_code, "@assyCode|subject");
disassy_code = first_xpath_string(NULL, dm_code, "@disassyCode|discode");
disassy_code_variant = first_xpath_string(NULL, dm_code, "@disassyCodeVariant|discodev");
info_code = first_xpath_string(NULL, dm_code, "@infoCode|incode");
info_code_variant = first_xpath_string(NULL, dm_code, "@infoCodeVariant|incodev");
item_location_code = first_xpath_string(NULL, dm_code, "@itemLocationCode|itemloc");
snprintf(dmc, 256, "%s-%s-%s-%s%s-%s-%s%s-%s%s-%s",
model_ident_code,
system_diff_code,
system_code,
sub_system_code,
sub_sub_system_code,
assy_code,
disassy_code,
disassy_code_variant,
info_code,
info_code_variant,
item_location_code);
snprintf(dm_fname, PATH_MAX, "DMC-%s", dmc);
if (!no_issue) {
strcpy(dm_fname_temp, dm_fname);
if (issue_info) {
issue_number = first_xpath_string(NULL, issue_info, "@issueNumber|@issno");
in_work = first_xpath_string(NULL, issue_info, "@inWork|@inwork");
if (snprintf(dm_fname, PATH_MAX, "%s_%s-%s", dm_fname_temp, issue_number, in_work ? in_work : "00") < 0) {
ENCODING_ERROR
}
} else if (language) {
if (snprintf(dm_fname, PATH_MAX, "%s_\?\?\?-\?\?", dm_fname_temp) < 0) {
ENCODING_ERROR
}
}
}
if (language) {
int i;
language_iso_code = first_xpath_string(NULL, language, "@languageIsoCode|@language");
country_iso_code = first_xpath_string(NULL, language, "@countryIsoCode|@country");
for (i = 0; language_iso_code[i]; ++i)
language_iso_code[i] = toupper(language_iso_code[i]);
strcpy(dm_fname_temp, dm_fname);
if (snprintf(dm_fname, PATH_MAX, "%s_%s-%s", dm_fname_temp, language_iso_code, country_iso_code) < 0) {
ENCODING_ERROR
}
}
xmlFree(model_ident_code);
xmlFree(system_diff_code);
xmlFree(system_code);
xmlFree(sub_system_code);
xmlFree(sub_sub_system_code);
xmlFree(assy_code);
xmlFree(disassy_code);
xmlFree(disassy_code_variant);
xmlFree(info_code);
xmlFree(info_code_variant);
xmlFree(item_location_code);
xmlFree(issue_number);
xmlFree(in_work);
xmlFree(language_iso_code);
xmlFree(country_iso_code);
for (cur = search_paths->children; cur && !found; cur = cur->next) {
char *path;
path = (char *) xmlNodeGetContent(cur);
if (verbosity >= DEBUG) {
fprintf(stderr, I_SEARCH, dm_fname, path);
}
if (find_csdb_object(fs_dm_fname, path, dm_fname, is_dm, recursive_search)) {
if (verbosity >= DEBUG) {
fprintf(stderr, I_FOUND, fs_dm_fname);
}
found = true;
/* Flatten a container data module by copying the
* dmRefs inside the container directly in to the
* publication module.
*/
if (flatten_container) {
xmlDocPtr doc;
xmlNodePtr refs;
doc = read_xml_doc(fs_dm_fname);
refs = first_xpath_node(doc, NULL, "//container/refs");
if (refs) {
xmlNodePtr c;
/* First, flatten the dmRefs in the
* container itself. */
flatten_pm_entry(refs, xiNs);
/* Copy each dmRef from the container
* into the PM. */
for (c = refs->last; c; c = c->prev) {
if (c->type != XML_ELEMENT_NODE) {
continue;
}
xmlAddNextSibling(dm_ref, xmlCopyNode(c, 1));
}
}
xmlFreeDoc(doc);
}
if (flatten_ref) {
if (verbosity >= VERBOSE) {
fprintf(stderr, I_INCLUDE, fs_dm_fname);
}
if (xinclude) {
xi = xmlNewNode(xiNs, BAD_CAST "include");
xmlSetProp(xi, BAD_CAST "href", BAD_CAST fs_dm_fname);
if (use_pub_fmt) {
xi = xmlAddChild(pub, xi);
} else {
xi = xmlAddPrevSibling(dm_ref, xi);
}
} else {
xmlChar *app;
doc = read_xml_doc(fs_dm_fname);
dmodule = xmlDocGetRootElement(doc);
if ((app = xmlGetProp(dm_ref, BAD_CAST "applicRefId"))) {
xmlSetProp(dmodule, BAD_CAST "applicRefId", app);
}
xmlFree(app);
xmlAddPrevSibling(dm_ref, xmlCopyNode(dmodule, 1));
xmlFreeDoc(doc);
}
}
} else if (remove_unresolved) {
if (verbosity >= VERBOSE) {
fprintf(stderr, I_REMOVE, dm_fname);
}
} else {
if (verbosity >= NORMAL) {
fprintf(stderr, W_MISSING_REF, dm_fname);
}
}
xmlFree(path);
}
if ((found && flatten_ref) || (!found && remove_unresolved)) {
xmlUnlinkNode(dm_ref);
xmlFreeNode(dm_ref);
}
}
static void flatten_pm_entry(xmlNodePtr pm_entry, xmlNsPtr xiNs)
{
xmlNodePtr cur, next;
cur = pm_entry->children;
while (cur) {
next = cur->next;
if (xmlStrcmp(cur->name, BAD_CAST "dmRef") == 0 || xmlStrcmp(cur->name, BAD_CAST "refdm") == 0) {
flatten_dm_ref(cur, xiNs);
} else if (xmlStrcmp(cur->name, BAD_CAST "pmRef") == 0 || xmlStrcmp(cur->name, BAD_CAST "refpm") == 0) {
flatten_pm_ref(cur, xiNs);
} else if (xmlStrcmp(cur->name, BAD_CAST "pmEntry") == 0 || xmlStrcmp(cur->name, BAD_CAST "pmentry") == 0) {
flatten_pm_entry(cur, xiNs);
}
cur = next;
}
if (xmlChildElementCount(pm_entry) == 0 ||
xmlStrcmp((cur = xmlLastElementChild(pm_entry))->name, BAD_CAST "pmEntryTitle") == 0 ||
xmlStrcmp(cur->name, BAD_CAST "title") == 0) {
xmlUnlinkNode(pm_entry);
xmlFreeNode(pm_entry);
}
}
static void transform_doc(xmlDocPtr doc, unsigned char *xml, unsigned int len, const char **params)
{
xmlDocPtr styledoc, res, src;
xsltStylesheetPtr style;
xmlNodePtr old;
styledoc = read_xml_mem((const char *) xml, len);
style = xsltParseStylesheetDoc(styledoc);
src = xmlCopyDoc(doc, 1);
res = xsltApplyStylesheet(style, src, params);
xmlFreeDoc(src);
old = xmlDocSetRootElement(doc, xmlCopyNode(xmlDocGetRootElement(res), 1));
xmlFreeNode(old);
xmlFreeDoc(res);
xsltFreeStylesheet(style);
}
static void remove_dup_refs(xmlDocPtr pm)
{
const char *params[5];
params[0] = "INF_PREFIX";
params[1] = "\"" INF_PREFIX "\"";
params[2] = "verbosity";
switch (verbosity) {
case QUIET: params[3] = "0"; break;
case NORMAL: params[3] = "1"; break;
case VERBOSE: params[3] = "2"; break;
case DEBUG: params[3] = "3"; break;
}
params[4] = NULL;
if (verbosity >= VERBOSE) {
fprintf(stderr, I_REMDUPS);
}
transform_doc(pm, xsl_remdups1_xsl, xsl_remdups1_xsl_len, NULL);
transform_doc(pm, xsl_remdups2_xsl, xsl_remdups2_xsl_len, params);
transform_doc(pm, ___common_remove_empty_pmentries_xsl, ___common_remove_empty_pmentries_xsl_len, NULL);
}
static void flatten_file(xmlNodePtr pub, xmlNsPtr xiNs, const char *fname)
{
if (xinclude) {
xmlNodePtr xi;
xi = xmlNewChild(pub, xiNs, BAD_CAST "include", NULL);
xmlSetProp(xi, BAD_CAST "href", BAD_CAST fname);
} else {
xmlDocPtr doc;
doc = read_xml_doc(fname);
xmlAddChild(pub, xmlCopyNode(xmlDocGetRootElement(doc), 1));
xmlFreeDoc(doc);
}
}
static void flatten_list(const char *path, xmlNodePtr pub, xmlNsPtr xiNs)
{
FILE *f = NULL;
char line[PATH_MAX];
if (path) {
if (!(fopen(path, "r"))) {
if (verbosity >= NORMAL) {
fprintf(stderr, E_BAD_LIST, path);
}
return;
}
} else {
f = stdin;
}
while (fgets(line, PATH_MAX, f)) {
strtok(line, "\t\r\n");
flatten_file(pub, xiNs, line);
}
if (path) {
fclose(f);
}
}
int main(int argc, char **argv)
{
int c;
char *pm_fname = NULL;
xmlNodePtr pm;
xmlNodePtr content;
xmlNodePtr cur;
const char *sopts = "cDd:fxmNPpqRruvI:ilh?";
struct option lopts[] = {
{"version" , no_argument , 0, 0},
{"help" , no_argument , 0, 'h'},
{"containers" , no_argument , 0, 'c'},
{"remove" , no_argument , 0, 'D'},
{"dir" , required_argument, 0, 'd'},
{"overwrite" , no_argument , 0, 'f'},
{"use-xinclude", no_argument , 0, 'x'},
{"modify" , no_argument , 0, 'm'},
{"omit-issue" , no_argument , 0, 'N'},
{"only-pm-refs", no_argument , 0, 'P'},
{"simple" , no_argument , 0, 'p'},
{"quiet" , no_argument , 0, 'q'},
{"recursively" , no_argument , 0, 'R'},
{"recursive" , no_argument , 0, 'r'},
{"unique" , no_argument , 0, 'u'},
{"verbose" , no_argument , 0, 'v'},
{"include" , required_argument, 0, 'I'},
{"ignore-issue", no_argument , 0, 'i'},
LIBXML2_PARSE_LONGOPT_DEFS
{0, 0, 0, 0}
};
int loptind = 0;
int overwrite = 0;
int remove_dups = 0;
bool is_list = false;
xmlNsPtr xiNs = NULL;
search_paths = xmlNewNode(NULL, BAD_CAST "searchPaths");
search_dir = strdup(".");
while ((c = getopt_long(argc, argv, sopts, lopts, &loptind)) != -1) {
switch (c) {
case 0:
if (strcmp(lopts[loptind].name, "version") == 0) {
show_version();
return 0;
}
LIBXML2_PARSE_LONGOPT_HANDLE(lopts, loptind, optarg)
break;
case 'c': flatten_container = 1; break;
case 'D': remove_unresolved = 1; break;
case 'd': free(search_dir); search_dir = strdup(optarg); break;
case 'f': overwrite = 1; break;
case 'x': xinclude = 1; break;
case 'm': flatten_ref = 0; break;
case 'N': no_issue = 1; break;
case 'P': only_pm_refs = 1; break;
case 'p': use_pub_fmt = 1; break;
case 'q': --verbosity; break;
case 'R': recursive = 1; break;
case 'r': recursive_search = 1; break;
case 'u': remove_dups = 1; break;
case 'v': ++verbosity; break;
case 'I': xmlNewChild(search_paths, NULL, BAD_CAST "path", BAD_CAST optarg); break;
case 'i': ignore_iss = 1; break;
case 'l': is_list = true; use_pub_fmt = 1; break;
case 'h':
case '?': show_help(); exit(0);
}
}
xmlNewChild(search_paths, NULL, BAD_CAST "path", BAD_CAST search_dir);
free(search_dir);
if (use_pub_fmt) {
pub_doc = xmlNewDoc(BAD_CAST "1.0");
pub = xmlNewNode(NULL, BAD_CAST "publication");
xmlDocSetRootElement(pub_doc, pub);
if (optind < argc) {
int i;
for (i = optind; i < argc; ++i) {
if (is_list) {
flatten_list(argv[i], pub, xiNs);
} else {
flatten_file(pub, xiNs, argv[i]);
}
}
} else if (is_list) {
flatten_list(NULL, pub, xiNs);
} else {
flatten_file(pub, xiNs, "-");
}
} else {
if (optind < argc) {
pm_fname = argv[optind];
} else {
pm_fname = "-";
}
if (!(pub_doc = read_xml_doc(pm_fname))) {
fprintf(stderr, E_BAD_PM, pm_fname);
exit(EXIT_BAD_PM);
}
pm = xmlDocGetRootElement(pub_doc);
content = find_child(pm, "content");
if (content) {
if (xinclude) {
xiNs = xmlNewNs(pm, BAD_CAST "http://www.w3.org/2001/XInclude", BAD_CAST "xi");
}
} else {
fprintf(stderr, E_BAD_PM, pm_fname);
exit(EXIT_BAD_PM);
}
cur = content->children;
while (cur) {
xmlNodePtr next;
next = cur->next;
if (xmlStrcmp(cur->name, BAD_CAST "pmEntry") == 0 || xmlStrcmp(cur->name, BAD_CAST "pmentry") == 0) {
flatten_pm_entry(cur, xiNs);
}
cur = next;
}
}
/* Remove duplicate entries from the flattened PM. */
if (remove_dups) {
remove_dup_refs(pub_doc);
}
save_xml_doc(pub_doc, (overwrite && !use_pub_fmt) ? pm_fname : "-");
xmlFreeNode(search_paths);
xmlFreeDoc(pub_doc);
xsltCleanupGlobals();
xmlCleanupParser();
return 0;
}
gopher://khzae.net/0/s1000d/s1kd-tools/src/tools/s1kd-flatten/s1kd-flatten.c