2 extern "C" int xmlLoadExtDtdDefaultValue
;
5 #include <config-kdoctools.h>
10 #include <libxml/xmlversion.h>
11 #include <libxml/xmlmemory.h>
12 #include <libxml/debugXML.h>
13 #include <libxml/HTMLtree.h>
14 #include <libxml/xmlIO.h>
15 #include <libxml/parserInternals.h>
16 #include <libxslt/xsltconfig.h>
17 #include <libxslt/xsltInternals.h>
18 #include <libxslt/transform.h>
19 #include <libxslt/xsltutils.h>
20 #include <QtCore/QString>
21 #include <kstandarddirs.h>
22 #include <kcomponentdata.h>
24 #include <QtCore/QFile>
25 #include <QtCore/QDir>
26 #include <kcmdlineargs.h>
28 #include <kaboutdata.h>
31 #include <QtCore/QTextCodec>
32 #include <QtCore/QFileInfo>
35 #include <QtCore/QList>
42 typedef QList
<MyPair
> PairList
;
44 void parseEntry(PairList
&list
, xmlNodePtr cur
, int base
)
49 base
+= atoi( ( const char* )xmlGetProp(cur
, ( const xmlChar
* )"header") );
50 if ( base
> 10 ) // 10 is the maximum
53 /* We don't care what the top level element name is */
54 cur
= cur
->xmlChildrenNode
;
57 if ( cur
->type
== XML_TEXT_NODE
) {
58 QString words
= QString::fromUtf8( ( char* )cur
->content
);
59 QStringList wlist
= words
.simplified().split( ' ',QString::SkipEmptyParts
);
60 for ( QStringList::ConstIterator it
= wlist
.begin();
61 it
!= wlist
.end(); ++it
)
68 } else if ( !xmlStrcmp( cur
->name
, (const xmlChar
*) "entry") )
69 parseEntry( list
, cur
, base
);
76 int main(int argc
, char **argv
) {
78 // xsltSetGenericDebugFunc(stderr, NULL);
80 KCmdLineOptions options
;
81 options
.add("stylesheet <xsl>", ki18n("Stylesheet to use"));
82 options
.add("stdout", ki18n("Output whole document to stdout"));
84 options
.add("output <file>", ki18n("Output whole document to file"));
85 options
.add("htdig", ki18n("Create a ht://dig compatible index"));
86 options
.add("check", ki18n("Check the document for validity"));
87 options
.add("cache <file>", ki18n("Create a cache file for the document"));
88 options
.add("srcdir <dir>", ki18n("Set the srcdir, for kdelibs"));
89 options
.add("param <key>=<value>", ki18n("Parameters to pass to the stylesheet"));
90 options
.add("+xml", ki18n("The file to transform"));
92 KAboutData
aboutData( "meinproc4", "kio_help4", ki18n("XML-Translator" ),
94 ki18n("KDE Translator for XML"));
96 KCmdLineArgs::init(argc
, argv
, &aboutData
, KCmdLineArgs::CmdLineArgKDE
);
97 KCmdLineArgs::addCmdLineOptions( options
);
99 KComponentData
ins("kio_help4");
103 KCmdLineArgs
*args
= KCmdLineArgs::parsedArgs();
104 if ( args
->count() != 1 ) {
109 // Need to set SRCDIR before calling fillInstance
111 if ( args
->isSet( "srcdir" ) )
112 srcdir
= QDir( args
->getOption( "srcdir" ) ).absolutePath();
113 fillInstance(ins
,srcdir
);
117 QString checkFilename
= args
->arg( 0 );
118 QFileInfo
checkFile(checkFilename
);
119 if (!checkFile
.exists())
121 kError() << "File '" << checkFilename
<< "' does not exist." << endl
;
124 if (!checkFile
.isFile())
126 kError() << "'" << checkFilename
<< "' is not a file." << endl
;
129 if (!checkFile
.isReadable())
131 kError() << "File '" << checkFilename
<< "' is not readable." << endl
;
135 if ( args
->isSet( "check" ) ) {
136 QString pwd_buffer
= QDir::currentPath();
137 QFileInfo
file( args
->arg( 0 ) );
140 catalogs
+= KUrl::fromLocalFile( KStandardDirs::locate( "dtd", "customization/catalog.xml" ) ).toEncoded();
142 catalogs
+= KUrl::fromLocalFile( KStandardDirs::locate( "dtd", "docbook/xml-dtd-4.1.2/catalog.xml" ) ).toEncoded();
144 setenv( "XML_CATALOG_FILES", catalogs
.constData(), 1 );
146 #if defined( XMLLINT )
149 if ( !QFileInfo( exe
).isExecutable() ) {
150 exe
= KStandardDirs::findExe( "xmllint" );
152 exe
= KStandardDirs::locate( "exe", "xmllint" );
154 if ( QFileInfo( exe
).isExecutable() ) {
155 QDir::setCurrent( file
.absolutePath() );
157 cmd
+= " --valid --noout ";
159 cmd
+= file
.fileName();
161 cmd
+= KShell::quoteArg(file
.fileName());
164 FILE *xmllint
= popen( QFile::encodeName( cmd
).constData(), "r" );
168 while ( ( n
= fread(buf
, 1, sizeof( buf
) - 1, xmllint
) ) ) {
171 fputs( buf
, stderr
);
174 QDir::setCurrent( pwd_buffer
);
178 kWarning() << "couldn't find xmllint";
182 xmlSubstituteEntitiesDefault(1);
183 xmlLoadExtDtdDefaultValue
= 1;
185 QVector
<const char *> params
;
187 // libxslt parses the path given to outputFile as XPath expression which fails
188 // see libxslt/xsltEvalUserParams
189 // this parameter is used only by share/apps/ksgmltools2/docbook/xsl/html/math.xsl
190 // and is not supported on windows yet
191 if (args
->isSet( "output" ) ) {
192 params
.append( qstrdup( "outputFile" ) );
193 params
.append( qstrdup( args
->getOption( "output" ).toLocal8Bit() ) );
197 const QStringList paramList
= args
->getOptionList( "param" );
198 QStringList::ConstIterator it
= paramList
.begin();
199 QStringList::ConstIterator end
= paramList
.end();
200 for ( ; it
!= end
; ++it
) {
201 const QString tuple
= *it
;
202 const int ch
= tuple
.indexOf( '=' );
204 kError() << "Key-Value tuple '" << tuple
<< "' lacks a '='!" << endl
;
207 params
.append( qstrdup( tuple
.left( ch
).toUtf8() ) );
208 params
.append( qstrdup( tuple
.mid( ch
+ 1 ).toUtf8() ) );
211 params
.append( NULL
);
213 bool index
= args
->isSet( "htdig" );
214 QString tss
= args
->getOption( "stylesheet" );
216 tss
= "customization/kde-chunk.xsl";
218 tss
= "customization/htdig_index.xsl" ;
220 tss
= KStandardDirs::locate( "dtd", tss
);
223 xsltStylesheetPtr style_sheet
=
224 xsltParseStylesheetFile((const xmlChar
*)tss
.toLatin1().data());
226 if (style_sheet
!= NULL
) {
228 xmlDocPtr doc
= xmlParseFile( QFile::encodeName( args
->arg( 0 ) ).constData() );
230 xmlDocPtr res
= xsltApplyStylesheet(style_sheet
, doc
, ¶ms
[0]);
233 xsltFreeStylesheet(style_sheet
);
235 xmlNodePtr cur
= xmlDocGetRootElement(res
);
236 if (!cur
|| xmlStrcmp(cur
->name
, (const xmlChar
*) "entry")) {
237 fprintf(stderr
,"document of the wrong type, root node != entry");
242 parseEntry( list
, cur
, 0 );
244 for ( PairList::ConstIterator it
= list
.begin(); it
!= list
.end();
246 fprintf( stdout
, "w\t%s\t%d\t%d\n", ( *it
).word
.toUtf8().data(),
247 1000*wi
/list
.count(), ( *it
).base
);
251 kDebug() << "couldn't parse document " << args
->arg( 0 );
254 kDebug() << "couldn't parse style sheet " << tss
;
258 QString output
= transform(args
->arg( 0 ) , tss
, params
);
259 if (output
.isEmpty()) {
260 fprintf(stderr
, "unable to parse %s\n", args
->arg( 0 ).toLocal8Bit().data());
264 QString cache
= args
->getOption( "cache" );
265 if ( !cache
.isEmpty() ) {
266 if ( !saveToCache( output
, cache
) ) {
267 kError() << i18n( "Could not write to cache file %1." , cache
) << endl
;
272 if (output
.indexOf( "<FILENAME " ) == -1 || args
->isSet( "stdout" ) || args
->isSet("output") )
275 if (args
->isSet( "stdout" ) ) {
276 file
.open( stdout
, QIODevice::WriteOnly
);
278 if (args
->isSet( "output" ) )
279 file
.setFileName( args
->getOption( "output" ));
281 file
.setFileName( "index.html" );
282 file
.open(QIODevice::WriteOnly
);
284 replaceCharsetHeader( output
);
286 QByteArray data
= output
.toLocal8Bit();
287 file
.write(data
.data(), data
.length());
292 index
= output
.indexOf("<FILENAME ", index
);
295 int filename_index
= index
+ strlen("<FILENAME filename=\"");
297 QString filename
= output
.mid(filename_index
,
298 output
.indexOf("\"", filename_index
) -
301 QString filedata
= splitOut(output
, index
);
302 QFile
file(filename
);
303 file
.open(QIODevice::WriteOnly
);
304 replaceCharsetHeader( filedata
);
305 QByteArray data
= fromUnicode( filedata
);
306 file
.write(data
.data(), data
.length());