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

KDocTools

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

Skip menu "kdelibs 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
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



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