• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.3 API Reference
  • KDE Home
  • Contact Us
 

KDocTools

xslt.cpp
Go to the documentation of this file.
00001 #include "xslt.h"
00002 
00003 #include <libxslt/xsltconfig.h>
00004 #include <libxslt/xsltInternals.h>
00005 #include <libxslt/transform.h>
00006 #include <libxslt/xsltutils.h>
00007 #include <libxml/xmlIO.h>
00008 #include <libxml/parserInternals.h>
00009 #include <libxml/catalog.h>
00010 #include <QtCore/QDate>
00011 #include <QtCore/QDir>
00012 #include <QtCore/QRegExp>
00013 #include <assert.h>
00014 #include <QtCore/QTextCodec>
00015 #include <stdlib.h>
00016 #include <stdarg.h>
00017 
00018 #ifdef Q_OS_WIN
00019 #include <config-kdoctools.h>
00020 #include <QtCore/QCoreApplication>
00021 #include <QtCore/QDebug>
00022 #include <QtCore/QHash>
00023 #endif
00024 
00025 #if !defined( SIMPLE_XSLT )
00026 extern HelpProtocol *slave;
00027 #define INFO( x ) if (slave) slave->infoMessage(x);
00028 #else
00029 #define INFO( x )
00030 #endif
00031 
00032 int writeToQString(void * context, const char * buffer, int len)
00033 {
00034     QString *t = (QString*)context;
00035     *t += QString::fromUtf8(buffer, len);
00036     return len;
00037 }
00038 
00039 int closeQString(void * context) {
00040     QString *t = (QString*)context;
00041     *t += '\n';
00042     return 0;
00043 }
00044 
00045 #if defined (SIMPLE_XSLT) && defined(Q_WS_WIN)
00046 
00047 #define MAX_PATHS 64 
00048 xmlExternalEntityLoader defaultEntityLoader = NULL;
00049 static xmlChar *paths[MAX_PATHS + 1]; 
00050 static int nbpaths = 0; 
00051 static QHash<QString,QString> replaceURLList;
00052 
00053 /*
00054 * Entity loading control and customization.
00055 * taken from xsltproc.c
00056 */
00057 static xmlParserInputPtr xsltprocExternalEntityLoader(const char *_URL, const char *ID,xmlParserCtxtPtr ctxt) 
00058 {
00059     xmlParserInputPtr ret;
00060     warningSAXFunc warning = NULL;
00061     
00062     // use local available dtd versions instead of fetching it everytime from the internet    
00063     QString url = QLatin1String(_URL);
00064     QHash<QString, QString>::const_iterator i;
00065     for(i = replaceURLList.constBegin(); i != replaceURLList.constEnd(); i++)
00066     {
00067         if (url.startsWith(i.key()))
00068         {
00069             url.replace(i.key(),i.value());
00070             qDebug() << "converted" << _URL << "to" << url;
00071         }
00072     }
00073     char URL[1024]; 
00074     strcpy(URL,url.toLatin1().constData());
00075 
00076     const char *lastsegment = URL;
00077     const char *iter = URL;
00078 
00079     if (nbpaths > 0) {
00080         while (*iter != 0) {
00081             if (*iter == '/')
00082             lastsegment = iter + 1;
00083             iter++;
00084         }
00085     }
00086 
00087     if ((ctxt != NULL) && (ctxt->sax != NULL)) {
00088         warning = ctxt->sax->warning;
00089         ctxt->sax->warning = NULL;
00090     }
00091         
00092     if (defaultEntityLoader != NULL) {
00093         ret = defaultEntityLoader(URL, ID, ctxt);
00094         if (ret != NULL) {
00095             if (warning != NULL)
00096                 ctxt->sax->warning = warning;
00097             qDebug() << "Loaded URL=\"" << URL << "\" ID=\"" << ID << "\"";
00098             return(ret);
00099         }
00100     }
00101     for (int i = 0;i < nbpaths;i++) {
00102         xmlChar *newURL;
00103 
00104         newURL = xmlStrdup((const xmlChar *) paths[i]);
00105         newURL = xmlStrcat(newURL, (const xmlChar *) "/");
00106         newURL = xmlStrcat(newURL, (const xmlChar *) lastsegment);
00107         if (newURL != NULL) {
00108             ret = defaultEntityLoader((const char *)newURL, ID, ctxt);
00109         if (ret != NULL) {
00110             if (warning != NULL)
00111                 ctxt->sax->warning = warning;
00112                 qDebug() << "Loaded URL=\"" << newURL << "\" ID=\"" << ID << "\"";
00113                 xmlFree(newURL);
00114                 return(ret);
00115             }
00116             xmlFree(newURL);
00117         }
00118     }
00119     if (warning != NULL) {
00120         ctxt->sax->warning = warning;
00121         if (URL != NULL)
00122             warning(ctxt, "failed to load external entity \"%s\"\n", URL);
00123         else if (ID != NULL)
00124             warning(ctxt, "failed to load external entity \"%s\"\n", ID);
00125     }
00126     return(NULL);
00127 } 
00128 #endif
00129 
00130 QString transform( const QString &pat, const QString& tss,
00131                    const QVector<const char *> &params )
00132 {
00133     QString parsed;
00134 
00135     INFO(i18n("Parsing stylesheet"));
00136 #if defined (SIMPLE_XSLT) && defined(Q_WS_WIN)
00137     // prepare use of local available dtd versions instead of fetching everytime from the internet
00138     // this approach is url based
00139     if (!defaultEntityLoader) {
00140         defaultEntityLoader = xmlGetExternalEntityLoader();
00141         xmlSetExternalEntityLoader(xsltprocExternalEntityLoader);
00142 
00143         replaceURLList[QLatin1String("http://www.oasis-open.org/docbook/xml/4.2")] = QString("file:///%1").arg(DOCBOOK_XML_CURRDTD);
00144     }
00145 #endif
00146 
00147     xsltStylesheetPtr style_sheet =
00148         xsltParseStylesheetFile((const xmlChar *)tss.toLatin1().data());
00149 
00150     if ( !style_sheet ) {
00151         return parsed;
00152     }
00153     if (style_sheet->indent == 1)
00154         xmlIndentTreeOutput = 1;
00155     else
00156         xmlIndentTreeOutput = 0;
00157 
00158     INFO(i18n("Parsing document"));
00159 
00160     xmlDocPtr doc = xmlParseFile( pat.toLatin1() );
00161     xsltTransformContextPtr ctxt;
00162 
00163     ctxt = xsltNewTransformContext(style_sheet, doc);
00164     if (ctxt == NULL)
00165         return parsed;
00166 
00167     INFO(i18n("Applying stylesheet"));
00168     QVector<const char *> p = params;
00169     p.append( NULL );
00170     xmlDocPtr res = xsltApplyStylesheet(style_sheet, doc, const_cast<const char **>(&p[0]));
00171     xmlFreeDoc(doc);
00172     if (res != NULL) {
00173         xmlOutputBufferPtr outp = xmlOutputBufferCreateIO(writeToQString, (xmlOutputCloseCallback)closeQString, &parsed, 0);
00174         outp->written = 0;
00175         INFO(i18n("Writing document"));
00176         xsltSaveResultTo ( outp, res, style_sheet );
00177         xmlOutputBufferFlush(outp);
00178         xmlFreeDoc(res);
00179     }
00180     xsltFreeStylesheet(style_sheet);
00181 
00182     if (parsed.isEmpty())
00183     parsed = ' '; // avoid error message
00184     return parsed;
00185 }
00186 
00187 /*
00188 xmlParserInputPtr meinExternalEntityLoader(const char *URL, const char *ID,
00189                        xmlParserCtxtPtr ctxt) {
00190     xmlParserInputPtr ret = NULL;
00191 
00192     // fprintf(stderr, "loading %s %s %s\n", URL, ID, ctxt->directory);
00193 
00194     if (URL == NULL) {
00195         if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
00196             ctxt->sax->warning(ctxt,
00197                     "failed to load external entity \"%s\"\n", ID);
00198         return(NULL);
00199     }
00200     if (!qstrcmp(ID, "-//OASIS//DTD DocBook XML V4.1.2//EN"))
00201         URL = "docbook/xml-dtd-4.1.2/docbookx.dtd";
00202     if (!qstrcmp(ID, "-//OASIS//DTD XML DocBook V4.1.2//EN"))
00203     URL = "docbook/xml-dtd-4.1.2/docbookx.dtd";
00204 
00205     QString file;
00206     if (KStandardDirs::exists( QDir::currentPath() + "/" + URL ) )
00207         file = QDir::currentPath() + "/" + URL;
00208     else
00209         file = locate("dtd", URL);
00210 
00211     ret = xmlNewInputFromFile(ctxt, file.toLatin1().constData());
00212     if (ret == NULL) {
00213         if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
00214             ctxt->sax->warning(ctxt,
00215 
00216                 "failed to load external entity \"%s\"\n", URL);
00217     }
00218     return(ret);
00219 }
00220 */
00221 
00222 QString splitOut(const QString &parsed, int index)
00223 {
00224     int start_index = index + 1;
00225     while (parsed.at(start_index - 1) != '>') start_index++;
00226 
00227     int inside = 0;
00228 
00229     QString filedata;
00230 
00231     while (true) {
00232         int endindex = parsed.indexOf("</FILENAME>", index);
00233         int startindex = parsed.indexOf("<FILENAME ", index) + 1;
00234 
00235 //        kDebug() << "FILENAME " << startindex << " " << endindex << " " << inside << " " << parsed.mid(startindex + 18, 15)<< " " << parsed.length();
00236 
00237         if (startindex > 0) {
00238             if (startindex < endindex) {
00239                 //              kDebug() << "finding another";
00240                 index = startindex + 8;
00241                 inside++;
00242             } else {
00243                 index = endindex + 8;
00244                 inside--;
00245             }
00246         } else {
00247             inside--;
00248             index = endindex + 1;
00249         }
00250 
00251         if (inside == 0) {
00252             filedata = parsed.mid(start_index, endindex - start_index);
00253             break;
00254         }
00255 
00256     }
00257 
00258     index = filedata.indexOf("<FILENAME ");
00259 
00260     if (index > 0) {
00261         int endindex = filedata.lastIndexOf("</FILENAME>");
00262         while (filedata.at(endindex) != '>') endindex++;
00263         endindex++;
00264         filedata = filedata.left(index) + filedata.mid(endindex);
00265     }
00266 
00267     // filedata.replace(QRegExp(">"), "\n>");
00268     return filedata;
00269 }
00270 
00271 QByteArray fromUnicode( const QString &data )
00272 {
00273 #ifdef Q_WS_WIN
00274     return data.toUtf8();
00275 #else
00276     QTextCodec *locale = QTextCodec::codecForLocale();
00277     QByteArray result;
00278     char buffer[30000];
00279     uint buffer_len = 0;
00280     uint len = 0;
00281     int offset = 0;
00282     const int part_len = 5000;
00283 
00284     QString part;
00285 
00286     while ( offset < data.length() )
00287     {
00288         part = data.mid( offset, part_len );
00289         QByteArray test = locale->fromUnicode( part );
00290         if ( locale->toUnicode( test ) == part ) {
00291             result += test;
00292             offset += part_len;
00293             continue;
00294         }
00295         len = part.length();
00296         buffer_len = 0;
00297         for ( uint i = 0; i < len; i++ ) {
00298             QByteArray test = locale->fromUnicode( part.mid( i, 1 ) );
00299             if ( locale->toUnicode( test ) == part.mid( i, 1 ) ) {
00300                 if (buffer_len + test.length() + 1 > sizeof(buffer))
00301                    break;
00302                 strcpy( buffer + buffer_len, test.data() );
00303                 buffer_len += test.length();
00304             } else {
00305                 QString res;
00306                 res.sprintf( "&#%d;", part.at( i ).unicode() );
00307                 test = locale->fromUnicode( res );
00308                 if (buffer_len + test.length() + 1 > sizeof(buffer))
00309                    break;
00310                 strcpy( buffer + buffer_len, test.data() );
00311                 buffer_len += test.length();
00312             }
00313         }
00314         result += QByteArray( buffer, buffer_len + 1);
00315         offset += part_len;
00316     }
00317     return result;
00318 #endif  
00319 }
00320 
00321 void replaceCharsetHeader( QString &output )
00322 {
00323     QString name;
00324 #ifdef Q_WS_WIN
00325     name = "utf-8"; 
00326     // may be required for all xml output 
00327     if (output.contains("<table-of-contents>"))
00328         output.replace( QString( "<?xml version=\"1.0\"?>" ),
00329                         QString( "<?xml version=\"1.0\" encoding=\"%1\"?>").arg( name ) );
00330 #else                    
00331     name = QTextCodec::codecForLocale()->name();
00332     name.replace( QString( "ISO " ), "iso-" );
00333     output.replace( QString( "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">" ),
00334                     QString( "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%1\">" ).arg( name ) );
00335 #endif    
00336 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:58:11 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDocTools

Skip menu "KDocTools"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.8.3 API Reference

Skip menu "kdelibs-4.8.3 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal