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

KDocTools

  • kdoctools
xslt.cpp
Go to the documentation of this file.
1#include "xslt.h"
2
3#include <libxslt/xsltconfig.h>
4#include <libxslt/xsltInternals.h>
5#include <libxslt/transform.h>
6#include <libxslt/xsltutils.h>
7#include <libxml/xmlIO.h>
8#include <libxml/xmlsave.h>
9#include <libxml/parserInternals.h>
10#include <libxml/catalog.h>
11#include <QtCore/QDate>
12#include <QtCore/QDir>
13#include <QtCore/QRegExp>
14#include <assert.h>
15#include <QtCore/QTextCodec>
16#include <stdlib.h>
17#include <stdarg.h>
18
19#ifdef Q_OS_WIN
20#include <config-kdoctools.h>
21#include <QtCore/QCoreApplication>
22#include <QtCore/QDebug>
23#include <QtCore/QHash>
24#endif
25
26#if !defined( SIMPLE_XSLT )
27extern HelpProtocol *slave;
28#define INFO( x ) if (slave) slave->infoMessage(x);
29#else
30#define INFO( x )
31#endif
32
33int writeToQString(void * context, const char * buffer, int len)
34{
35 QString *t = (QString*)context;
36 *t += QString::fromUtf8(buffer, len);
37 return len;
38}
39
40int closeQString(void * context) {
41 QString *t = (QString*)context;
42 *t += '\n';
43 return 0;
44}
45
46#if defined (SIMPLE_XSLT) && defined(Q_WS_WIN)
47
48#define MAX_PATHS 64
49xmlExternalEntityLoader defaultEntityLoader = NULL;
50static xmlChar *paths[MAX_PATHS + 1];
51static int nbpaths = 0;
52static QHash<QString,QString> replaceURLList;
53
54/*
55* Entity loading control and customization.
56* taken from xsltproc.c
57*/
58static xmlParserInputPtr xsltprocExternalEntityLoader(const char *_URL, const char *ID,xmlParserCtxtPtr ctxt)
59{
60 xmlParserInputPtr ret;
61 warningSAXFunc warning = NULL;
62
63 // use local available dtd versions instead of fetching it everytime from the internet
64 QString url = QLatin1String(_URL);
65 QHash<QString, QString>::const_iterator i;
66 for(i = replaceURLList.constBegin(); i != replaceURLList.constEnd(); i++)
67 {
68 if (url.startsWith(i.key()))
69 {
70 url.replace(i.key(),i.value());
71 qDebug() << "converted" << _URL << "to" << url;
72 }
73 }
74 char URL[1024];
75 strcpy(URL,url.toLatin1().constData());
76
77 const char *lastsegment = URL;
78 const char *iter = URL;
79
80 if (nbpaths > 0) {
81 while (*iter != 0) {
82 if (*iter == '/')
83 lastsegment = iter + 1;
84 iter++;
85 }
86 }
87
88 if ((ctxt != NULL) && (ctxt->sax != NULL)) {
89 warning = ctxt->sax->warning;
90 ctxt->sax->warning = NULL;
91 }
92
93 if (defaultEntityLoader != NULL) {
94 ret = defaultEntityLoader(URL, ID, ctxt);
95 if (ret != NULL) {
96 if (warning != NULL)
97 ctxt->sax->warning = warning;
98 qDebug() << "Loaded URL=\"" << URL << "\" ID=\"" << ID << "\"";
99 return(ret);
100 }
101 }
102 for (int i = 0;i < nbpaths;i++) {
103 xmlChar *newURL;
104
105 newURL = xmlStrdup((const xmlChar *) paths[i]);
106 newURL = xmlStrcat(newURL, (const xmlChar *) "/");
107 newURL = xmlStrcat(newURL, (const xmlChar *) lastsegment);
108 if (newURL != NULL) {
109 ret = defaultEntityLoader((const char *)newURL, ID, ctxt);
110 if (ret != NULL) {
111 if (warning != NULL)
112 ctxt->sax->warning = warning;
113 qDebug() << "Loaded URL=\"" << newURL << "\" ID=\"" << ID << "\"";
114 xmlFree(newURL);
115 return(ret);
116 }
117 xmlFree(newURL);
118 }
119 }
120 if (warning != NULL) {
121 ctxt->sax->warning = warning;
122 if (URL != NULL)
123 warning(ctxt, "failed to load external entity \"%s\"\n", URL);
124 else if (ID != NULL)
125 warning(ctxt, "failed to load external entity \"%s\"\n", ID);
126 }
127 return(NULL);
128}
129#endif
130
131QString transform( const QString &pat, const QString& tss,
132 const QVector<const char *> &params )
133{
134 QString parsed;
135
136 INFO(i18n("Parsing stylesheet"));
137#if defined (SIMPLE_XSLT) && defined(Q_WS_WIN)
138 // prepare use of local available dtd versions instead of fetching everytime from the internet
139 // this approach is url based
140 if (!defaultEntityLoader) {
141 defaultEntityLoader = xmlGetExternalEntityLoader();
142 xmlSetExternalEntityLoader(xsltprocExternalEntityLoader);
143
144 replaceURLList[QLatin1String("http://www.oasis-open.org/docbook/xml/4.2")] = QString("file:///%1").arg(DOCBOOK_XML_CURRDTD);
145 }
146#endif
147
148 xsltStylesheetPtr style_sheet =
149 xsltParseStylesheetFile((const xmlChar *)QFile::encodeName(tss).constData());
150
151 if ( !style_sheet ) {
152 return parsed;
153 }
154 if (style_sheet->indent == 1)
155 xmlIndentTreeOutput = 1;
156 else
157 xmlIndentTreeOutput = 0;
158
159 INFO(i18n("Parsing document"));
160
161 xmlParserCtxtPtr pctxt;
162
163 pctxt = xmlNewParserCtxt();
164 if ( pctxt == NULL ) {
165 return parsed;
166 }
167
168 xmlDocPtr doc = xmlCtxtReadFile(pctxt, QFile::encodeName(pat), NULL,
169 XML_PARSE_NOENT|XML_PARSE_DTDLOAD|XML_PARSE_NONET);
170 /* Check both the returned doc (for parsing errors) and the context
171 (for validation errors) */
172 if (doc == NULL) {
173 return parsed;
174 } else {
175 if (pctxt->valid == 0) {
176 xmlFreeDoc(doc);
177 return parsed;
178 }
179 }
180
181 xsltTransformContextPtr ctxt;
182
183 ctxt = xsltNewTransformContext(style_sheet, doc);
184 if (ctxt == NULL)
185 return parsed;
186
187 INFO(i18n("Applying stylesheet"));
188 QVector<const char *> p = params;
189 p.append( NULL );
190 xmlDocPtr res = xsltApplyStylesheet(style_sheet, doc, const_cast<const char **>(&p[0]));
191 xmlFreeDoc(doc);
192 if (res != NULL) {
193 xmlOutputBufferPtr outp = xmlOutputBufferCreateIO(writeToQString, (xmlOutputCloseCallback)closeQString, &parsed, 0);
194 outp->written = 0;
195 INFO(i18n("Writing document"));
196 xsltSaveResultTo ( outp, res, style_sheet );
197 xmlOutputBufferFlush(outp);
198 xmlFreeDoc(res);
199 }
200 xsltFreeStylesheet(style_sheet);
201
202 if (parsed.isEmpty())
203 parsed = ' '; // avoid error message
204 return parsed;
205}
206
207/*
208xmlParserInputPtr meinExternalEntityLoader(const char *URL, const char *ID,
209 xmlParserCtxtPtr ctxt) {
210 xmlParserInputPtr ret = NULL;
211
212 // fprintf(stderr, "loading %s %s %s\n", URL, ID, ctxt->directory);
213
214 if (URL == NULL) {
215 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
216 ctxt->sax->warning(ctxt,
217 "failed to load external entity \"%s\"\n", ID);
218 return(NULL);
219 }
220 if (!qstrcmp(ID, "-//OASIS//DTD DocBook XML V4.1.2//EN"))
221 URL = "docbook/xml-dtd-4.1.2/docbookx.dtd";
222 if (!qstrcmp(ID, "-//OASIS//DTD XML DocBook V4.1.2//EN"))
223 URL = "docbook/xml-dtd-4.1.2/docbookx.dtd";
224
225 QString file;
226 if (KStandardDirs::exists( QDir::currentPath() + "/" + URL ) )
227 file = QDir::currentPath() + "/" + URL;
228 else
229 file = locate("dtd", URL);
230
231 ret = xmlNewInputFromFile(ctxt, file.toLatin1().constData());
232 if (ret == NULL) {
233 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
234 ctxt->sax->warning(ctxt,
235
236 "failed to load external entity \"%s\"\n", URL);
237 }
238 return(ret);
239}
240*/
241
242QString splitOut(const QString &parsed, int index)
243{
244 int start_index = index + 1;
245 while (parsed.at(start_index - 1) != '>') start_index++;
246
247 int inside = 0;
248
249 QString filedata;
250
251 while (true) {
252 int endindex = parsed.indexOf("</FILENAME>", index);
253 int startindex = parsed.indexOf("<FILENAME ", index) + 1;
254
255// kDebug() << "FILENAME " << startindex << " " << endindex << " " << inside << " " << parsed.mid(startindex + 18, 15)<< " " << parsed.length();
256
257 if (startindex > 0) {
258 if (startindex < endindex) {
259 // kDebug() << "finding another";
260 index = startindex + 8;
261 inside++;
262 } else {
263 index = endindex + 8;
264 inside--;
265 }
266 } else {
267 inside--;
268 index = endindex + 1;
269 }
270
271 if (inside == 0) {
272 filedata = parsed.mid(start_index, endindex - start_index);
273 break;
274 }
275
276 }
277
278 index = filedata.indexOf("<FILENAME ");
279
280 if (index > 0) {
281 int endindex = filedata.lastIndexOf("</FILENAME>");
282 while (filedata.at(endindex) != '>') endindex++;
283 endindex++;
284 filedata = filedata.left(index) + filedata.mid(endindex);
285 }
286
287 // filedata.replace(QRegExp(">"), "\n>");
288 return filedata;
289}
290
291QByteArray fromUnicode( const QString &data )
292{
293#ifdef Q_WS_WIN
294 return data.toUtf8();
295#else
296 QTextCodec *locale = QTextCodec::codecForLocale();
297 QByteArray result;
298 char buffer[30000];
299 uint buffer_len = 0;
300 uint len = 0;
301 int offset = 0;
302 const int part_len = 5000;
303
304 QString part;
305
306 while ( offset < data.length() )
307 {
308 part = data.mid( offset, part_len );
309 QByteArray test = locale->fromUnicode( part );
310 if ( locale->toUnicode( test ) == part ) {
311 result += test;
312 offset += part_len;
313 continue;
314 }
315 len = part.length();
316 buffer_len = 0;
317 for ( uint i = 0; i < len; i++ ) {
318 QByteArray test = locale->fromUnicode( part.mid( i, 1 ) );
319 if ( locale->toUnicode( test ) == part.mid( i, 1 ) ) {
320 if (buffer_len + test.length() + 1 > sizeof(buffer))
321 break;
322 strcpy( buffer + buffer_len, test.data() );
323 buffer_len += test.length();
324 } else {
325 QString res;
326 res.sprintf( "&#%d;", part.at( i ).unicode() );
327 test = locale->fromUnicode( res );
328 if (buffer_len + test.length() + 1 > sizeof(buffer))
329 break;
330 strcpy( buffer + buffer_len, test.data() );
331 buffer_len += test.length();
332 }
333 }
334 result += QByteArray( buffer, buffer_len + 1);
335 offset += part_len;
336 }
337 return result;
338#endif
339}
340
341void replaceCharsetHeader( QString &output )
342{
343 QString name;
344#ifdef Q_WS_WIN
345 name = "utf-8";
346 // may be required for all xml output
347 if (output.contains("<table-of-contents>"))
348 output.replace( QString( "<?xml version=\"1.0\"?>" ),
349 QString( "<?xml version=\"1.0\" encoding=\"%1\"?>").arg( name ) );
350#else
351 name = QTextCodec::codecForLocale()->name();
352 name.replace( QString( "ISO " ), "iso-" );
353 output.replace( QString( "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">" ),
354 QString( "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%1\">" ).arg( name ) );
355#endif
356}
HelpProtocol
Definition kio_help.h:37
QHash
output
void output(QList< Action > actions, QHash< QString, QString > domain)
slave
HelpProtocol * slave
Definition kio_help.cpp:174
i18n
QString i18n(const char *text)
writeToQString
int writeToQString(void *context, const char *buffer, int len)
Definition xslt.cpp:33
replaceCharsetHeader
void replaceCharsetHeader(QString &output)
Definition xslt.cpp:341
splitOut
QString splitOut(const QString &parsed, int index)
Definition xslt.cpp:242
closeQString
int closeQString(void *context)
Definition xslt.cpp:40
fromUnicode
QByteArray fromUnicode(const QString &data)
Definition xslt.cpp:291
INFO
#define INFO(x)
Definition xslt.cpp:28
transform
QString transform(const QString &pat, const QString &tss, const QVector< const char * > &params)
Definition xslt.cpp:131
xslt.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Tue Mar 25 2025 00:00:00 by doxygen 1.14.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDocTools

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

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 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