5 #include <libxml/xmlversion.h>
6 #include <libxml/xmlmemory.h>
7 #include <libxml/debugXML.h>
8 #include <libxml/HTMLtree.h>
9 #include <libxml/xmlIO.h>
10 #include <libxml/parserInternals.h>
11 #include <libxslt/xsltconfig.h>
12 #include <libxslt/xsltInternals.h>
13 #include <libxslt/transform.h>
14 #include <libxslt/xsltutils.h>
16 #include <kstandarddirs.h>
17 #include <kinstance.h>
21 #include <tdecmdlineargs.h>
22 #include <tdelocale.h>
23 #include <tdeaboutdata.h>
26 #include <tqtextcodec.h>
27 #include <tqfileinfo.h>
29 #include <tqvaluevector.h>
31 extern int xmlLoadExtDtdDefaultValue;
38 typedef TQValueList<MyPair> PairList;
40 void parseEntry(PairList &list, xmlNodePtr cur,
int base)
45 base += atoi( (
const char* )xmlGetProp(cur, (
const xmlChar* )
"header") );
50 cur = cur->xmlChildrenNode;
53 if ( cur->type == XML_TEXT_NODE ) {
54 TQString words = TQString::fromUtf8( (
char* )cur->content );
55 TQStringList wlist = TQStringList::split(
' ', words.simplifyWhiteSpace() );
56 for ( TQStringList::ConstIterator it = wlist.begin();
57 it != wlist.end(); ++it )
64 }
else if ( !xmlStrcmp( cur->name, (
const xmlChar *)
"entry") )
65 parseEntry( list, cur, base );
72 static TDECmdLineOptions options[] =
74 {
"stylesheet <xsl>", I18N_NOOP(
"Stylesheet to use" ), 0 },
75 {
"stdout", I18N_NOOP(
"Output whole document to stdout" ), 0 },
77 {
"output <file>", I18N_NOOP(
"Output whole document to file" ), 0 },
78 {
"htdig", I18N_NOOP(
"Create a ht://dig compatible index" ), 0 },
79 {
"check", I18N_NOOP(
"Check the document for validity" ), 0 },
80 {
"cache <file>", I18N_NOOP(
"Create a cache file for the document" ), 0},
81 {
"srcdir <dir>", I18N_NOOP(
"Set the srcdir, for tdelibs" ), 0},
82 {
"param <key>=<value>", I18N_NOOP(
"Parameters to pass to the stylesheet" ), 0},
83 {
"+xml", I18N_NOOP(
"The file to transform"), 0},
90 int main(
int argc,
char **argv) {
94 TDEAboutData aboutData(
"meinproc", I18N_NOOP(
"XML-Translator" ),
96 I18N_NOOP(
"TDE Translator for XML"));
98 TDECmdLineArgs::init(argc, argv, &aboutData);
99 TDECmdLineArgs::addCmdLineOptions( options );
101 TDELocale::setMainCatalogue(
"tdeio_help");
102 TDEInstance ins(
"meinproc");
106 TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
107 if ( args->count() != 1 ) {
114 if ( args->isSet(
"srcdir" ) )
115 srcdir = TQDir( TQFile::decodeName( args->getOption(
"srcdir" ) ) ).absPath();
116 fillInstance(ins,srcdir);
120 TQString checkFilename = TQFile::decodeName(args->arg( 0 ));
121 TQFileInfo checkFile(checkFilename);
122 if (!checkFile.exists())
124 kdError() <<
"File '" << checkFilename <<
"' does not exist." << endl;
127 if (!checkFile.isFile())
129 kdError() <<
"'" << checkFilename <<
"' is not a file." << endl;
132 if (!checkFile.isReadable())
134 kdError() <<
"File '" << checkFilename <<
"' is not readable." << endl;
138 if ( args->isSet(
"check" ) ) {
139 #if !defined(PATH_MAX) && defined(__GLIBC__)
142 char pwd_buffer[PATH_MAX];
144 TQFileInfo file( TQFile::decodeName(args->arg( 0 )) );
145 #if !defined(PATH_MAX) && defined(__GLIBC__)
146 if ( !(pwd_buffer = getcwd( NULL, 0 ) ) )
148 if ( !getcwd( pwd_buffer,
sizeof(pwd_buffer) - 1 ) )
151 kdError() <<
"getcwd failed." << endl;
156 catalogs += locate(
"dtd",
"customization/catalog.xml" );
158 catalogs += locate(
"dtd",
"docbook/xml-dtd-4.1.2/catalog.xml" );
160 setenv(
"XML_CATALOG_FILES", TQFile::encodeName( catalogs ).data(), 1);
162 #if defined( XMLLINT )
165 if ( (::access( TQFile::encodeName( exe ), X_OK )!=0) ) {
166 exe = TDEStandardDirs::findExe(
"xmllint" );
168 exe = locate(
"exe",
"xmllint" );
170 if ( ::access( TQFile::encodeName( exe ), X_OK )==0 ) {
171 chdir( TQFile::encodeName( file.dirPath(
true ) ) );
173 cmd +=
" --valid --noout ";
174 cmd += TDEProcess::quote(file.fileName());
176 FILE *xmllint = popen( TQFile::encodeName( cmd ),
"r");
180 while ( ( n = fread(buf, 1,
sizeof( buf ), xmllint ) ) ) {
183 fputs( buf, stderr );
188 #if !defined(PATH_MAX) && defined(__GLIBC__)
194 kdWarning() <<
"couldn't find xmllint" << endl;
196 #if !defined(PATH_MAX) && defined(__GLIBC__)
201 xmlSubstituteEntitiesDefault(1);
202 xmlLoadExtDtdDefaultValue = 1;
204 TQValueVector<const char *> params;
205 if (args->isSet(
"output" ) ) {
206 params.append( tqstrdup(
"outputFile" ) );
207 params.append( tqstrdup( TQString(TQFile::decodeName( args->getOption(
"output" ) )).latin1() ) );
210 const QCStringList paramList = args->getOptionList(
"param" );
211 QCStringList::ConstIterator it = paramList.begin();
212 QCStringList::ConstIterator end = paramList.end();
213 for ( ; it != end; ++it ) {
214 const TQCString tuple = *it;
215 const int ch = tuple.find(
'=' );
217 kdError() <<
"Key-Value tuple '" << tuple <<
"' lacks a '='!" << endl;
220 params.append( tqstrdup( tuple.left( ch ) ) );
221 params.append( tqstrdup( tuple.mid( ch + 1 ) ) );
224 params.append( NULL );
226 bool index = args->isSet(
"htdig" );
227 TQString tss = args->getOption(
"stylesheet" );
229 tss =
"customization/tde-chunk.xsl";
231 tss =
"customization/htdig_index.xsl" ;
233 tss = locate(
"dtd", tss );
236 xsltStylesheetPtr style_sheet =
237 xsltParseStylesheetFile((
const xmlChar *)tss.latin1());
239 if (style_sheet != NULL) {
241 xmlDocPtr doc = xmlParseFile( TQFile::encodeName( args->arg( 0 ) ) );
243 xmlDocPtr res = xsltApplyStylesheet(style_sheet, doc, ¶ms[0]);
246 xsltFreeStylesheet(style_sheet);
248 xmlNodePtr cur = xmlDocGetRootElement(res);
249 if (!cur || xmlStrcmp(cur->name, (
const xmlChar *)
"entry")) {
250 fprintf(stderr,
"document of the wrong type, root node != entry");
255 parseEntry( list, cur, 0 );
257 for ( PairList::ConstIterator it = list.begin(); it != list.end();
259 fprintf( stdout,
"w\t%s\t%d\t%d\n", ( *it ).word.utf8().data(),
260 1000*wi/(int)list.count(), ( *it ).base );
264 kdDebug() <<
"couldn't parse document " << args->arg( 0 ) << endl;
267 kdDebug() <<
"couldn't parse style sheet " << tss << endl;
271 TQString output = transform(args->arg( 0 ) , tss, params);
272 if (output.isEmpty()) {
273 fprintf(stderr,
"unable to parse %s\n", args->arg( 0 ));
277 TQString cache = args->getOption(
"cache" );
278 if ( !cache.isEmpty() ) {
279 if ( !saveToCache( output, cache ) ) {
280 kdError() << TQString(i18n(
"Could not write to cache file %1." ).arg( cache )) << endl;
285 if (output.find(
"<FILENAME " ) == -1 || args->isSet(
"stdout" ) || args->isSet(
"output") )
288 if (args->isSet(
"stdout" ) ) {
289 file.open( IO_WriteOnly, stdout );
291 if (args->isSet(
"output" ) )
292 file.setName( TQFile::decodeName(args->getOption(
"output" )));
294 file.setName(
"index.html" );
295 file.open(IO_WriteOnly);
297 replaceCharsetHeader( output );
299 TQCString data = output.local8Bit();
300 file.writeBlock(data.data(), data.length());
305 index = output.find(
"<FILENAME ", index);
308 int filename_index = index + strlen(
"<FILENAME filename=\"");
310 TQString filename = output.mid(filename_index,
311 output.find(
"\"", filename_index) -
314 TQString filedata = splitOut(output, index);
315 TQFile file(filename);
316 file.open(IO_WriteOnly);
317 replaceCharsetHeader( filedata );
318 TQCString data = fromUnicode( filedata );
319 file.writeBlock(data.data(), data.length());