kde-playground/khelpcenter/slave/xslt.cpp
Ivailo Monev 2cf532fa19 generic: misc cleanups and adjustments
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2016-05-14 10:12:10 +00:00

236 lines
6.8 KiB
C++

#include "xslt.h"
#include <libxslt/xsltconfig.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include <libxml/xmlIO.h>
#include <libxml/parserInternals.h>
#include <libxml/catalog.h>
#include <QtCore/QDate>
#include <QtCore/QDir>
#include <QtCore/QRegExp>
#include <QtCore/QTextCodec>
#include <klocale.h>
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#define INFO( x )
int writeToQString(void * context, const char * buffer, int len)
{
QString *t = (QString*)context;
*t += QString::fromUtf8(buffer, len);
return len;
}
int closeQString(void * context) {
QString *t = (QString*)context;
*t += '\n';
return 0;
}
QString transform( const QString &pat, const QString& tss,
const QVector<const char *> &params )
{
QString parsed;
INFO(i18n("Parsing stylesheet"));
xsltStylesheetPtr style_sheet =
xsltParseStylesheetFile((const xmlChar *)QFile::encodeName(tss).constData());
if ( !style_sheet ) {
return parsed;
}
if (style_sheet->indent == 1)
xmlIndentTreeOutput = 1;
else
xmlIndentTreeOutput = 0;
INFO(i18n("Parsing document"));
xmlParserCtxtPtr pctxt;
pctxt = xmlNewParserCtxt();
if ( pctxt == NULL ) {
return parsed;
}
xmlDocPtr doc = xmlCtxtReadFile(pctxt, QFile::encodeName(pat), NULL,
XML_PARSE_NOENT|XML_PARSE_DTDLOAD|XML_PARSE_NONET);
/* Check both the returned doc (for parsing errors) and the context
(for validation errors) */
if (doc == NULL) {
return parsed;
} else {
if (pctxt->valid == 0) {
xmlFreeDoc(doc);
return parsed;
}
}
xsltTransformContextPtr ctxt;
ctxt = xsltNewTransformContext(style_sheet, doc);
if (ctxt == NULL)
return parsed;
INFO(i18n("Applying stylesheet"));
QVector<const char *> p = params;
p.append( NULL );
xmlDocPtr res = xsltApplyStylesheet(style_sheet, doc, const_cast<const char **>(&p[0]));
xmlFreeDoc(doc);
if (res != NULL) {
xmlOutputBufferPtr outp = xmlOutputBufferCreateIO(writeToQString, (xmlOutputCloseCallback)closeQString, &parsed, 0);
outp->written = 0;
INFO(i18n("Writing document"));
xsltSaveResultTo ( outp, res, style_sheet );
xmlOutputBufferFlush(outp);
xmlFreeDoc(res);
}
xsltFreeStylesheet(style_sheet);
if (parsed.isEmpty())
parsed = ' '; // avoid error message
return parsed;
}
/*
xmlParserInputPtr meinExternalEntityLoader(const char *URL, const char *ID,
xmlParserCtxtPtr ctxt) {
xmlParserInputPtr ret = NULL;
// fprintf(stderr, "loading %s %s %s\n", URL, ID, ctxt->directory);
if (URL == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt,
"failed to load external entity \"%s\"\n", ID);
return(NULL);
}
if (!qstrcmp(ID, "-//OASIS//DTD DocBook XML V4.1.2//EN"))
URL = "docbook/xml-dtd-4.1.2/docbookx.dtd";
if (!qstrcmp(ID, "-//OASIS//DTD XML DocBook V4.1.2//EN"))
URL = "docbook/xml-dtd-4.1.2/docbookx.dtd";
QString file;
if (KGlobal::dirs()->exists( QDir::currentPath() + "/" + URL ) )
file = QDir::currentPath() + "/" + URL;
else
file = locate("dtd", URL);
ret = xmlNewInputFromFile(ctxt, file.toLatin1().constData());
if (ret == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt,
"failed to load external entity \"%s\"\n", URL);
}
return(ret);
}
*/
QString splitOut(const QString &parsed, int index)
{
int start_index = index + 1;
while (parsed.at(start_index - 1) != '>') start_index++;
int inside = 0;
QString filedata;
while (true) {
int endindex = parsed.indexOf("</FILENAME>", index);
int startindex = parsed.indexOf("<FILENAME ", index) + 1;
// kDebug() << "FILENAME " << startindex << " " << endindex << " " << inside << " " << parsed.mid(startindex + 18, 15)<< " " << parsed.length();
if (startindex > 0) {
if (startindex < endindex) {
// kDebug() << "finding another";
index = startindex + 8;
inside++;
} else {
index = endindex + 8;
inside--;
}
} else {
inside--;
index = endindex + 1;
}
if (inside == 0) {
filedata = parsed.mid(start_index, endindex - start_index);
break;
}
}
index = filedata.indexOf("<FILENAME ");
if (index > 0) {
int endindex = filedata.lastIndexOf("</FILENAME>");
while (filedata.at(endindex) != '>') endindex++;
endindex++;
filedata = filedata.left(index) + filedata.mid(endindex);
}
// filedata.replace(QRegExp(">"), "\n>");
return filedata;
}
QByteArray fromUnicode( const QString &data )
{
QTextCodec *locale = QTextCodec::codecForLocale();
QByteArray result;
char buffer[30000];
uint buffer_len = 0;
uint len = 0;
int offset = 0;
const int part_len = 5000;
QString part;
while ( offset < data.length() )
{
part = data.mid( offset, part_len );
QByteArray test = locale->fromUnicode( part );
if ( locale->toUnicode( test ) == part ) {
result += test;
offset += part_len;
continue;
}
len = part.length();
buffer_len = 0;
for ( uint i = 0; i < len; i++ ) {
QByteArray test = locale->fromUnicode( part.mid( i, 1 ) );
if ( locale->toUnicode( test ) == part.mid( i, 1 ) ) {
if (buffer_len + test.length() + 1 > sizeof(buffer))
break;
strcpy( buffer + buffer_len, test.data() );
buffer_len += test.length();
} else {
QString res;
res.sprintf( "&#%d;", part.at( i ).unicode() );
test = locale->fromUnicode( res );
if (buffer_len + test.length() + 1 > sizeof(buffer))
break;
strcpy( buffer + buffer_len, test.data() );
buffer_len += test.length();
}
}
result += QByteArray( buffer, buffer_len + 1);
offset += part_len;
}
return result;
}
void replaceCharsetHeader( QString &output )
{
QString name;
name = QTextCodec::codecForLocale()->name();
name.replace( QString( "ISO " ), "iso-" );
output.replace( QString( "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">" ),
QString( "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%1\">" ).arg( name ) );
}