KDocTools
meinproc.cpp
Go to the documentation of this file.
00001 00002 #include <config-kdoctools.h> 00003 #include <config.h> 00004 #include "xslt.h" 00005 #include "meinproc_common.h" 00006 00007 #include <QCoreApplication> 00008 #include <QtCore/QString> 00009 #include <QtCore/QFile> 00010 #include <QtCore/QDir> 00011 #include <QtCore/QTextCodec> 00012 #include <QtCore/QFileInfo> 00013 #include <QtCore/QList> 00014 00015 #include <kaboutdata.h> 00016 #include <kcomponentdata.h> 00017 #include <kcmdlineargs.h> 00018 #include <kdebug.h> 00019 #include <klocale.h> 00020 #include <kstandarddirs.h> 00021 #include <kshell.h> 00022 #include <kurl.h> 00023 00024 #include <libxml/xmlversion.h> 00025 #include <libxml/xmlmemory.h> 00026 #include <libxml/debugXML.h> 00027 #include <libxml/HTMLtree.h> 00028 #include <libxml/xmlIO.h> 00029 #include <libxml/parserInternals.h> 00030 #include <libxslt/xsltconfig.h> 00031 #include <libxslt/xsltInternals.h> 00032 #include <libxslt/transform.h> 00033 #include <libxslt/xsltutils.h> 00034 #include <libexslt/exslt.h> 00035 00036 #include <stdlib.h> 00037 #include <string.h> 00038 #include <sys/time.h> 00039 #include <unistd.h> 00040 00041 #ifndef _WIN32 00042 extern "C" int xmlLoadExtDtdDefaultValue; 00043 #endif 00044 00045 class MyPair { 00046 public: 00047 QString word; 00048 int base;}; 00049 00050 typedef QList<MyPair> PairList; 00051 00052 void parseEntry(PairList &list, xmlNodePtr cur, int base) 00053 { 00054 if ( !cur ) 00055 return; 00056 00057 base += atoi( ( const char* )xmlGetProp(cur, ( const xmlChar* )"header") ); 00058 if ( base > 10 ) // 10 is the maximum 00059 base = 10; 00060 00061 /* We don't care what the top level element name is */ 00062 cur = cur->xmlChildrenNode; 00063 while (cur != NULL) { 00064 00065 if ( cur->type == XML_TEXT_NODE ) { 00066 QString words = QString::fromUtf8( ( char* )cur->content ); 00067 const QStringList wlist = words.simplified().split( ' ',QString::SkipEmptyParts ); 00068 for ( QStringList::ConstIterator it = wlist.begin(); 00069 it != wlist.end(); ++it ) 00070 { 00071 MyPair m; 00072 m.word = *it; 00073 m.base = base; 00074 list.append( m ); 00075 } 00076 } else if ( !xmlStrcmp( cur->name, (const xmlChar *) "entry") ) 00077 parseEntry( list, cur, base ); 00078 00079 cur = cur->next; 00080 } 00081 00082 } 00083 00084 int main(int argc, char **argv) { 00085 00086 // xsltSetGenericDebugFunc(stderr, NULL); 00087 00088 KCmdLineOptions options; 00089 options.add("stylesheet <xsl>", ki18n("Stylesheet to use")); 00090 options.add("stdout", ki18n("Output whole document to stdout")); 00091 options.add("o"); 00092 options.add("output <file>", ki18n("Output whole document to file")); 00093 options.add("htdig", ki18n("Create a ht://dig compatible index")); 00094 options.add("check", ki18n("Check the document for validity")); 00095 options.add("cache <file>", ki18n("Create a cache file for the document")); 00096 options.add("srcdir <dir>", ki18n("Set the srcdir, for kdelibs")); 00097 options.add("param <key>=<value>", ki18n("Parameters to pass to the stylesheet")); 00098 options.add("+xml", ki18n("The file to transform")); 00099 00100 KAboutData aboutData( "meinproc4", "kio_help4", ki18n("XML-Translator" ), 00101 "$Revision$", 00102 ki18n("KDE Translator for XML")); 00103 00104 KCmdLineArgs::init(argc, argv, &aboutData, KCmdLineArgs::CmdLineArgKDE); 00105 KCmdLineArgs::addCmdLineOptions( options ); 00106 00107 QCoreApplication app( argc, argv ); 00108 KComponentData ins("kio_help4"); 00109 KGlobal::locale(); 00110 00111 KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); 00112 if ( args->count() != 1 ) { 00113 args->usage(); 00114 return ( 1 ); 00115 } 00116 00117 exsltRegisterAll(); 00118 00119 // Need to set SRCDIR before calling fillInstance 00120 QString srcdir; 00121 if ( args->isSet( "srcdir" ) ) 00122 srcdir = QDir( args->getOption( "srcdir" ) ).absolutePath(); 00123 fillInstance(ins,srcdir); 00124 00125 LIBXML_TEST_VERSION 00126 00127 const QString checkFilename = args->arg( 0 ); 00128 CheckFileResult ckr = checkFile( checkFilename ); 00129 if ( ckr != CheckFileSuccess ) 00130 { 00131 if ( ckr == CheckFileDoesNotExist ) kError() << "File '" << checkFilename << "' does not exist."; 00132 else if ( ckr == CheckFileIsNotFile ) kError() << "'" << checkFilename << "' is not a file."; 00133 else if ( ckr == CheckFileIsNotReadable ) kError() << "File '" << checkFilename << "' is not readable."; 00134 return ( 2 ); 00135 } 00136 00137 if ( args->isSet( "check" ) ) { 00138 00139 QByteArray catalogs; 00140 catalogs += KUrl::fromLocalFile( KStandardDirs::locate( "dtd", "customization/catalog.xml" ) ).toEncoded(); 00141 00142 QString exe; 00143 #if defined( XMLLINT ) 00144 exe = XMLLINT; 00145 #endif 00146 if ( !QFileInfo( exe ).isExecutable() ) { 00147 exe = KStandardDirs::findExe( "xmllint" ); 00148 if (exe.isEmpty()) 00149 exe = KStandardDirs::locate( "exe", "xmllint" ); 00150 } 00151 00152 CheckResult cr = check( checkFilename, exe, catalogs ); 00153 if ( cr != CheckSuccess ) 00154 { 00155 if ( cr == CheckNoXmllint ) kWarning() << "couldn't find xmllint"; 00156 return 1; 00157 } 00158 } 00159 00160 xmlSubstituteEntitiesDefault(1); 00161 xmlLoadExtDtdDefaultValue = 1; 00162 00163 QVector<const char *> params; 00164 #ifndef Q_WS_WIN 00165 // libxslt parses the path given to outputFile as XPath expression which fails 00166 // see libxslt/xsltEvalUserParams 00167 // this parameter is used only by share/apps/ksgmltools2/docbook/xsl/html/math.xsl 00168 // and is not supported on windows yet 00169 if (args->isSet( "output" ) ) { 00170 params.append( qstrdup( "outputFile" ) ); 00171 params.append( qstrdup( args->getOption( "output" ).toLocal8Bit() ) ); 00172 } 00173 #endif 00174 { 00175 const QStringList paramList = args->getOptionList( "param" ); 00176 QStringList::ConstIterator it = paramList.begin(); 00177 QStringList::ConstIterator end = paramList.end(); 00178 for ( ; it != end; ++it ) { 00179 const QString tuple = *it; 00180 const int ch = tuple.indexOf( '=' ); 00181 if ( ch == -1 ) { 00182 kError() << "Key-Value tuple '" << tuple << "' lacks a '='!" << endl; 00183 return( 2 ); 00184 } 00185 params.append( qstrdup( tuple.left( ch ).toUtf8() ) ); 00186 params.append( qstrdup( tuple.mid( ch + 1 ).toUtf8() ) ); 00187 } 00188 } 00189 params.append( NULL ); 00190 00191 bool index = args->isSet( "htdig" ); 00192 QString tss = args->getOption( "stylesheet" ); 00193 if ( tss.isEmpty() ) 00194 tss = "customization/kde-chunk.xsl"; 00195 if ( index ) 00196 tss = "customization/htdig_index.xsl" ; 00197 00198 tss = KStandardDirs::locate( "dtd", tss ); 00199 const QString cache = args->getOption( "cache" ); 00200 const bool usingStdOut = args->isSet( "stdout" ); 00201 const bool usingOutput = args->isSet("output"); 00202 const QString outputOption = args->getOption( "output" ); 00203 00204 if ( index ) { 00205 xsltStylesheetPtr style_sheet = 00206 xsltParseStylesheetFile((const xmlChar *)tss.toLatin1().data()); 00207 00208 if (style_sheet != NULL) { 00209 00210 xmlDocPtr doc = xmlParseFile( QFile::encodeName( checkFilename ).constData() ); 00211 00212 xmlDocPtr res = xsltApplyStylesheet(style_sheet, doc, ¶ms[0]); 00213 00214 xmlFreeDoc(doc); 00215 xsltFreeStylesheet(style_sheet); 00216 if (res != NULL) { 00217 xmlNodePtr cur = xmlDocGetRootElement(res); 00218 if (!cur || xmlStrcmp(cur->name, (const xmlChar *) "entry")) { 00219 fprintf(stderr,"document of the wrong type, root node != entry"); 00220 xmlFreeDoc(res); 00221 return(1); 00222 } 00223 PairList list; 00224 parseEntry( list, cur, 0 ); 00225 int wi = 0; 00226 for ( PairList::ConstIterator it = list.constBegin(); it != list.constEnd(); 00227 ++it, ++wi ) 00228 fprintf( stdout, "w\t%s\t%d\t%d\n", ( *it ).word.toUtf8().data(), 00229 1000*wi/list.count(), ( *it ).base ); 00230 00231 xmlFreeDoc(res); 00232 } else { 00233 kDebug() << "couldn't parse document " << checkFilename; 00234 } 00235 } else { 00236 kDebug() << "couldn't parse style sheet " << tss; 00237 } 00238 00239 } else { 00240 QString output = transform(checkFilename , tss, params); 00241 if (output.isEmpty()) { 00242 fprintf(stderr, "unable to parse %s\n", checkFilename.toLocal8Bit().data()); 00243 return(1); 00244 } 00245 00246 if ( !cache.isEmpty() ) { 00247 if ( !saveToCache( output, cache ) ) { 00248 kError() << i18n( "Could not write to cache file %1." , cache ) << endl; 00249 } 00250 goto end; 00251 } 00252 00253 doOutput(output, usingStdOut, usingOutput, outputOption, true /* replaceCharset */); 00254 } 00255 end: 00256 xmlCleanupParser(); 00257 xmlMemoryDump(); 00258 return(0); 00259 } 00260
KDE 4.6 API Reference