8 #include <libxml/xmlversion.h>
9 #include <libxml/xmlmemory.h>
10 #include <libxml/debugXML.h>
11 #include <libxml/HTMLtree.h>
12 #include <libxml/xmlIO.h>
13 #include <libxml/parserInternals.h>
14 #include <libxslt/xsltconfig.h>
15 #include <libxslt/xsltInternals.h>
16 #include <libxslt/transform.h>
17 #include <libxslt/xsltutils.h>
19 #include <kstandarddirs.h>
20 #include <kinstance.h>
24 #include <tdecmdlineargs.h>
25 #include <tdelocale.h>
26 #include <tdeaboutdata.h>
29 #include <tqtextcodec.h>
30 #include <tqfileinfo.h>
31 #include <tdeprocess.h>
32 #include <tqvaluevector.h>
34 extern int xmlLoadExtDtdDefaultValue;
41 typedef TQValueList<MyPair> PairList;
43 void parseEntry(PairList &list, xmlNodePtr cur,
int base)
48 base += atoi( (
const char* )xmlGetProp(cur, (
const xmlChar* )
"header") );
53 cur = cur->xmlChildrenNode;
56 if ( cur->type == XML_TEXT_NODE ) {
57 TQString words = TQString::fromUtf8( (
char* )cur->content );
58 TQStringList wlist = TQStringList::split(
' ', words.simplifyWhiteSpace() );
59 for ( TQStringList::ConstIterator it = wlist.begin();
60 it != wlist.end(); ++it )
67 }
else if ( !xmlStrcmp( cur->name, (
const xmlChar *)
"entry") )
68 parseEntry( list, cur, base );
75 static TDECmdLineOptions options[] =
77 {
"stylesheet <xsl>", I18N_NOOP(
"Stylesheet to use" ), 0 },
78 {
"stdout", I18N_NOOP(
"Output whole document to stdout" ), 0 },
80 {
"output <file>", I18N_NOOP(
"Output whole document to file" ), 0 },
81 {
"htdig", I18N_NOOP(
"Create a ht://dig compatible index" ), 0 },
82 {
"check", I18N_NOOP(
"Check the document for validity" ), 0 },
83 {
"cache <file>", I18N_NOOP(
"Create a cache file for the document" ), 0},
84 {
"srcdir <dir>", I18N_NOOP(
"Set the srcdir, for tdelibs" ), 0},
85 {
"param <key>=<value>", I18N_NOOP(
"Parameters to pass to the stylesheet" ), 0},
86 {
"+xml", I18N_NOOP(
"The file to transform"), 0},
93 int main(
int argc,
char **argv) {
97 TDEAboutData aboutData(
"meinproc", I18N_NOOP(
"XML-Translator" ),
99 I18N_NOOP(
"TDE Translator for XML"));
101 TDECmdLineArgs::init(argc, argv, &aboutData);
102 TDECmdLineArgs::addCmdLineOptions( options );
104 TDELocale::setMainCatalogue(
"tdeio_help");
105 TDEInstance ins(
"meinproc");
109 TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
110 if ( args->count() != 1 ) {
117 if ( args->isSet(
"srcdir" ) )
118 srcdir = TQDir( TQFile::decodeName( args->getOption(
"srcdir" ) ) ).absPath();
119 fillInstance(ins,srcdir);
123 TQString checkFilename = TQFile::decodeName(args->arg( 0 ));
124 TQFileInfo checkFile(checkFilename);
125 if (!checkFile.exists())
127 kdError() <<
"File '" << checkFilename <<
"' does not exist." << endl;
130 if (!checkFile.isFile())
132 kdError() <<
"'" << checkFilename <<
"' is not a file." << endl;
135 if (!checkFile.isReadable())
137 kdError() <<
"File '" << checkFilename <<
"' is not readable." << endl;
141 if ( args->isSet(
"check" ) ) {
142 #if !defined(PATH_MAX) && defined(__GLIBC__)
145 char pwd_buffer[PATH_MAX];
147 TQFileInfo file( TQFile::decodeName(args->arg( 0 )) );
148 #if !defined(PATH_MAX) && defined(__GLIBC__)
149 if ( !(pwd_buffer = getcwd( NULL, 0 ) ) )
151 if ( !getcwd( pwd_buffer,
sizeof(pwd_buffer) - 1 ) )
154 kdError() <<
"getcwd failed." << endl;
159 catalogs += locate(
"dtd",
"customization/catalog.xml" );
161 catalogs += locate(
"dtd",
"docbook/xml-dtd-4.1.2/catalog.xml" );
163 setenv(
"XML_CATALOG_FILES", TQFile::encodeName( catalogs ).data(), 1);
165 #if defined( XMLLINT )
168 if ( (::access( TQFile::encodeName( exe ), X_OK )!=0) ) {
169 exe = TDEStandardDirs::findExe(
"xmllint" );
171 exe = locate(
"exe",
"xmllint" );
173 if ( ::access( TQFile::encodeName( exe ), X_OK )==0 ) {
174 chdir( TQFile::encodeName( file.dirPath(
true ) ) );
176 cmd +=
" --valid --noout ";
177 cmd += TDEProcess::quote(file.fileName());
179 FILE *xmllint = popen( TQFile::encodeName( cmd ),
"r");
183 while ( ( n = fread(buf, 1,
sizeof( buf ), xmllint ) ) ) {
186 fputs( buf, stderr );
191 #if !defined(PATH_MAX) && defined(__GLIBC__)
197 kdWarning() <<
"couldn't find xmllint" << endl;
199 #if !defined(PATH_MAX) && defined(__GLIBC__)
204 xmlSubstituteEntitiesDefault(1);
205 xmlLoadExtDtdDefaultValue = 1;
207 TQValueVector<const char *> params;
208 if (args->isSet(
"output" ) ) {
209 params.append( tqstrdup(
"outputFile" ) );
210 params.append( tqstrdup( TQString(TQFile::decodeName( args->getOption(
"output" ) )).latin1() ) );
213 const QCStringList paramList = args->getOptionList(
"param" );
214 QCStringList::ConstIterator it = paramList.begin();
215 QCStringList::ConstIterator end = paramList.end();
216 for ( ; it != end; ++it ) {
217 const TQCString tuple = *it;
218 const int ch = tuple.find(
'=' );
220 kdError() <<
"Key-Value tuple '" << tuple <<
"' lacks a '='!" << endl;
223 params.append( tqstrdup( tuple.left( ch ) ) );
224 params.append( tqstrdup( tuple.mid( ch + 1 ) ) );
227 params.append( NULL );
229 bool index = args->isSet(
"htdig" );
230 TQString tss = args->getOption(
"stylesheet" );
232 tss =
"customization/tde-chunk.xsl";
234 tss =
"customization/htdig_index.xsl" ;
236 tss = locate(
"dtd", tss );
239 xsltStylesheetPtr style_sheet =
240 xsltParseStylesheetFile((
const xmlChar *)tss.latin1());
242 if (style_sheet != NULL) {
244 xmlDocPtr doc = xmlParseFile( TQFile::encodeName( args->arg( 0 ) ) );
246 xmlDocPtr res = xsltApplyStylesheet(style_sheet, doc, ¶ms[0]);
249 xsltFreeStylesheet(style_sheet);
251 xmlNodePtr cur = xmlDocGetRootElement(res);
252 if (!cur || xmlStrcmp(cur->name, (
const xmlChar *)
"entry")) {
253 fprintf(stderr,
"document of the wrong type, root node != entry");
258 parseEntry( list, cur, 0 );
260 for ( PairList::ConstIterator it = list.begin(); it != list.end();
262 fprintf( stdout,
"w\t%s\t%d\t%d\n", ( *it ).word.utf8().data(),
263 1000*wi/(
int)list.count(), ( *it ).base );
267 kdDebug() <<
"couldn't parse document " << args->arg( 0 ) << endl;
270 kdDebug() <<
"couldn't parse style sheet " << tss << endl;
274 TQString output = transform(args->arg( 0 ) , tss, params);
275 if (output.isEmpty()) {
276 fprintf(stderr,
"unable to parse %s\n", args->arg( 0 ));
280 TQString cache = args->getOption(
"cache" );
281 if ( !cache.isEmpty() ) {
282 if ( !saveToCache( output, cache ) ) {
283 kdError() << TQString(i18n(
"Could not write to cache file %1." ).arg( cache )) << endl;
288 if (output.find(
"<FILENAME " ) == -1 || args->isSet(
"stdout" ) || args->isSet(
"output") )
291 if (args->isSet(
"stdout" ) ) {
292 file.open( IO_WriteOnly, stdout );
294 if (args->isSet(
"output" ) )
295 file.setName( TQFile::decodeName(args->getOption(
"output" )));
297 file.setName(
"index.html" );
298 file.open(IO_WriteOnly);
300 replaceCharsetHeader( output );
302 TQCString data = output.local8Bit();
303 file.writeBlock(data.data(), data.length());
308 index = output.find(
"<FILENAME ", index);
311 int filename_index = index + strlen(
"<FILENAME filename=\"");
313 TQString filename = output.mid(filename_index,
314 output.find(
"\"", filename_index) -
317 TQString filedata = splitOut(output, index);
318 TQFile file(filename);
319 file.open(IO_WriteOnly);
320 replaceCharsetHeader( filedata );
321 TQCString data = fromUnicode( filedata );
322 file.writeBlock(data.data(), data.length());