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

jovie

  • sources
  • kde-4.12
  • kdeaccessibility
  • jovie
  • filters
  • xmltransformer
xmltransformerproc.cpp
Go to the documentation of this file.
1 /***************************************************** vim:set ts=4 sw=4 sts=4:
2  Generic XML Transformation Filter Processing class.
3  -------------------
4  Copyright:
5  (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
6  -------------------
7  Original author: Gary Cramblitt <garycramblitt@comcast.net>
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  ******************************************************************************/
23 
24 // XmlTransformer includes.
25 #include "xmltransformerproc.h"
26 #include "xmltransformerproc.moc"
27 
28 // Qt includes.
29 #include <QtCore/QFile>
30 #include <QtCore/QLatin1String>
31 #include <QtCore/QRegExp>
32 #include <QtCore/QTextStream>
33 
34 // KDE includes.
35 #include <kdeversion.h>
36 #include <kconfig.h>
37 #include <kconfiggroup.h>
38 #include <ktemporaryfile.h>
39 #include <kstandarddirs.h>
40 #include <kdebug.h>
41 
42 // KTTS includes.
43 #include "filterproc.h"
44 #include "utils.h"
45 
49 XmlTransformerProc::XmlTransformerProc( QObject *parent, const QVariantList& args) :
50  KttsFilterProc(parent, args)
51 {
52  m_xsltProc = 0;
53 }
54 
58 /*virtual*/ XmlTransformerProc::~XmlTransformerProc()
59 {
60  delete m_xsltProc;
61  if (!m_inFilename.isEmpty()) QFile::remove(m_inFilename);
62  if (!m_outFilename.isEmpty()) QFile::remove(m_outFilename);
63 }
64 
65 bool XmlTransformerProc::init(KConfig* c, const QString& configGroup)
66 {
67  // kDebug() << "XmlTransformerProc::init: Running.";
68  KConfigGroup config( c, configGroup );
69  m_UserFilterName = config.readEntry( "UserFilterName" );
70  m_xsltFilePath = config.readEntry( "XsltFilePath" );
71  m_xsltprocPath = config.readEntry( "XsltprocPath" );
72  m_rootElementList = config.readEntry( "RootElement", QStringList() );
73  m_doctypeList = config.readEntry( "DocType", QStringList() );
74  m_appIdList = config.readEntry( "AppID", QStringList() );
75  kDebug() << "XmlTransformerProc::init: m_xsltprocPath = " << m_xsltprocPath;
76  kDebug() << "XmlTransformerProc::init: m_xsltFilePath = " << m_xsltFilePath;
77  return ( m_xsltFilePath.isEmpty() || m_xsltprocPath.isEmpty() );
78 }
79 
90 /*virtual*/ bool XmlTransformerProc::supportsAsync() { return true; }
91 
101 /*virtual*/ QString XmlTransformerProc::convert(const QString& inputText, TalkerCode* talkerCode,
102  const QString& appId)
103 {
104  // kDebug() << "XmlTransformerProc::convert: Running.";
105  // If not properly configured, do nothing.
106  if ( m_xsltFilePath.isEmpty() || m_xsltprocPath.isEmpty() )
107  {
108  kDebug() << "XmlTransformerProc::convert: not properly configured";
109  return inputText;
110  }
111  // Asynchronously convert and wait for completion.
112  if (asyncConvert(inputText, talkerCode, appId))
113  {
114  waitForFinished();
115  m_state = fsIdle;
116  return m_text;
117  } else
118  return inputText;
119 }
120 
121 bool XmlTransformerProc::asyncConvert(const QString& inputText, TalkerCode* talkerCode,
122  const QString& appId)
123 {
124  Q_UNUSED(talkerCode);
125  m_wasModified = false;
126 
127  // kDebug() << "XmlTransformerProc::asyncConvert: Running.";
128  m_text = inputText;
129  // If not properly configured, do nothing.
130  if ( m_xsltFilePath.isEmpty() || m_xsltprocPath.isEmpty() )
131  {
132  kDebug() << "XmlTransformerProc::asyncConvert: not properly configured.";
133  return false;
134  }
135 
136  bool found = false;
137  // If not correct XML type, or DOCTYPE, do nothing.
138  if ( !m_rootElementList.isEmpty() )
139  {
140  // kDebug() << "XmlTransformerProc::asyncConvert:: searching for root elements " << m_rootElementList;
141  for ( int ndx=0; ndx < m_rootElementList.count(); ++ndx )
142  {
143  if ( KttsUtils::hasRootElement( inputText, m_rootElementList[ndx] ) )
144  {
145  found = true;
146  break;
147  }
148  }
149  if ( !found && m_doctypeList.isEmpty() )
150  {
151  kDebug() << "XmlTransformerProc::asyncConvert: Did not find root element(s)" << m_rootElementList;
152  return false;
153  }
154  }
155  if ( !found && !m_doctypeList.isEmpty() )
156  {
157  for ( int ndx=0; ndx < m_doctypeList.count(); ++ndx )
158  {
159  if ( KttsUtils::hasDoctype( inputText, m_doctypeList[ndx] ) )
160  {
161  found = true;
162  break;
163  }
164  }
165  if ( !found )
166  {
167  // kDebug() << "XmlTransformerProc::asyncConvert: Did not find doctype(s)" << m_doctypeList;
168  return false;
169  }
170  }
171 
172  // If appId doesn't match, return input unmolested.
173  if ( !m_appIdList.isEmpty() )
174  {
175  QString appIdStr = appId;
176  // kDebug() << "XmlTransformrProc::convert: converting " << inputText << " if appId "
177  // << appId << " matches " << m_appIdList << endl;
178  found = false;
179  for ( int ndx=0; ndx < m_appIdList.count(); ++ndx )
180  {
181  if ( appIdStr.contains(m_appIdList[ndx]) )
182  {
183  found = true;
184  break;
185  }
186  }
187  if ( !found )
188  {
189  // kDebug() << "XmlTransformerProc::asyncConvert: Did not find appId(s)" << m_appIdList;
190  return false;
191  }
192  }
193 
195  KTemporaryFile inFile;
196  inFile.setPrefix(QLatin1String( "kttsd-" ));
197  inFile.setSuffix(QLatin1String( ".xml" ));
198  inFile.setAutoRemove(false);
199  inFile.open();
200  m_inFilename = inFile.fileName();
201  QTextStream wstream (&inFile);
202  // TODO: Is encoding an issue here?
203  // If input does not have xml processing instruction, add it.
204  if (!inputText.startsWith(QLatin1String("<?xml"))) wstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
205  // FIXME: Temporary Fix until Konqi returns properly formatted xhtml with & coded as &amp;
206  // This will change & inside a CDATA section, which is not good, and also within comments and
207  // processing instructions, which is OK because we don't speak those anyway.
208  QString text = inputText;
209  text.replace(QRegExp(QLatin1String( "&(?!amp;)") ),QLatin1String( "&amp;" ));
210  wstream << text;
211  inFile.flush();
212 
213  // Get a temporary output file name.
214  KTemporaryFile outFile;
215  outFile.setPrefix(QLatin1String( "kttsd-" ));
216  outFile.setSuffix(QLatin1String( ".output" ));
217  outFile.setAutoRemove(false);
218  outFile.open();
219  m_outFilename = outFile.fileName();
220 
222  m_xsltProc = new KProcess;
223  m_xsltProc->setOutputChannelMode(KProcess::SeparateChannels);
224  *m_xsltProc << m_xsltprocPath;
225  *m_xsltProc << QLatin1String("-o") << m_outFilename << QLatin1String("--novalid")
226  << m_xsltFilePath << m_inFilename;
227  // Warning: This won't compile under KDE 3.2. See FreeTTS::argsToStringList().
228  // kDebug() << "SSMLConvert::transform: executing command: " <<
229  // m_xsltProc->args() << endl;
230 
231  m_state = fsFiltering;
232  connect(m_xsltProc, SIGNAL(finished(int,QProcess::ExitStatus)),
233  this, SLOT(slotProcessExited(int,QProcess::ExitStatus)));
234  connect(m_xsltProc, SIGNAL(readyReadStandardOutput()),
235  this, SLOT(slotReceivedStdout()));
236  connect(m_xsltProc, SIGNAL(readyReadStandardError()),
237  this, SLOT(slotReceivedStderr()));
238  m_xsltProc->start();
239  if (!m_xsltProc->waitForStarted())
240  {
241  kDebug() << "XmlTransformerProc::convert: Error starting xsltproc";
242  m_state = fsIdle;
243  return false;
244  }
245  return true;
246 }
247 
248 // Process output when xsltproc exits.
249 void XmlTransformerProc::processOutput()
250 {
251  QFile::remove(m_inFilename);
252 
253  int exitStatus = 11;
254  if (m_xsltProc->exitStatus() == QProcess::NormalExit)
255  exitStatus = m_xsltProc->exitCode();
256  else
257  kDebug() << "XmlTransformerProc::processOutput: xsltproc was killed.";
258 
259  delete m_xsltProc;
260  m_xsltProc = 0;
261 
262  if (exitStatus != 0)
263  {
264  kDebug() << "XmlTransformerProc::processOutput: xsltproc abnormal exit. Status = " << exitStatus;
265  m_state = fsFinished;
266  QFile::remove(m_outFilename);
267  emit filteringFinished();
268  return;
269  }
270 
272  QFile readfile(m_outFilename);
273  if(!readfile.open(QIODevice::ReadOnly)) {
275  kDebug() << "XmlTransformerProc::processOutput: Could not read file " << m_outFilename;
276  m_state = fsFinished;
277  emit filteringFinished();
278  }
279  QTextStream rstream(&readfile);
280  m_text = rstream.readAll();
281  readfile.close();
282 
283  kDebug() << QLatin1String( "XmlTransformerProc::processOutput: Read file at " ) + m_inFilename + QLatin1String( " and created " ) + m_outFilename + QLatin1String( " based on the stylesheet at " ) << m_xsltFilePath;
284 
285  // Clean up.
286  QFile::remove(m_outFilename);
287 
288  m_state = fsFinished;
289  m_wasModified = true;
290  emit filteringFinished();
291 }
292 
296 /*virtual*/ void XmlTransformerProc::waitForFinished()
297 {
298  if (m_xsltProc)
299  {
300  if (m_xsltProc->state() != QProcess::NotRunning)
301  {
302  if ( !m_xsltProc->waitForFinished( 15 ) )
303  {
304  m_xsltProc->kill();
305  kDebug() << "XmlTransformerProc::waitForFinished: After waiting 15 seconds, xsltproc process seems to hung. Killing it.";
306  processOutput();
307  }
308  }
309  }
310 }
311 
315 /*virtual*/ int XmlTransformerProc::getState() { return m_state; }
316 
320 /*virtual*/ QString XmlTransformerProc::getOutput() { return m_text; }
321 
325 /*virtual*/ void XmlTransformerProc::ackFinished()
326 {
327  m_state = fsIdle;
328  m_text.clear();
329 }
330 
335 /*virtual*/ void XmlTransformerProc::stopFiltering()
336 {
337  m_state = fsStopping;
338  m_xsltProc->kill();
339 }
340 
345 /*virtual*/ bool XmlTransformerProc::wasModified() { return m_wasModified; }
346 
347 void XmlTransformerProc::slotProcessExited(int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/)
348 {
349  // kDebug() << "XmlTransformerProc::slotProcessExited: xsltproc has exited.";
350  processOutput();
351 }
352 
353 void XmlTransformerProc::slotReceivedStdout()
354 {
355  // QString buf = QString::fromLatin1(buffer, buflen);
356  // kDebug() << "XmlTransformerProc::slotReceivedStdout: Received from xsltproc: " << buf;
357 }
358 
359 void XmlTransformerProc::slotReceivedStderr()
360 {
361  // QString buf = QString::fromLatin1(buffer, buflen);
362  // kDebug() << "XmlTransformerProc::slotReceivedStderr: Received error from xsltproc: " << buf;
363 }
364 
XmlTransformerProc::ackFinished
virtual void ackFinished()
Acknowledges the finished filtering.
Definition: xmltransformerproc.cpp:325
XmlTransformerProc::asyncConvert
virtual bool asyncConvert(const QString &inputText, TalkerCode *talkerCode, const QString &appId)
Convert input.
Definition: xmltransformerproc.cpp:121
KttsUtils::hasRootElement
static bool hasRootElement(const QString &xmldoc, const QString &elementName)
Check if an XML document has a certain root element.
Definition: utils.cpp:37
KttsFilterProc::filteringFinished
void filteringFinished()
Emitted when asynchronous filtering has completed.
KttsUtils::hasDoctype
static bool hasDoctype(const QString &xmldoc, const QString &name)
Check if an XML document has a certain DOCTYPE.
Definition: utils.cpp:76
KttsFilterProc::fsFinished
Definition: filterproc.h:47
QObject
XmlTransformerProc::waitForFinished
virtual void waitForFinished()
Waits for a previous call to asyncConvert to finish.
Definition: xmltransformerproc.cpp:296
KttsFilterProc::fsStopping
Definition: filterproc.h:46
utils.h
XmlTransformerProc::getState
virtual int getState()
Returns the state of the Filter.
Definition: xmltransformerproc.cpp:315
filterproc.h
KttsFilterProc
Definition: filterproc.h:38
XmlTransformerProc::wasModified
virtual bool wasModified()
Did this filter do anything? If the filter returns the input as output unmolested, it should return False when this method is called.
Definition: xmltransformerproc.cpp:345
TalkerCode
Definition: talkercode.h:38
XmlTransformerProc::init
virtual bool init(KConfig *c, const QString &configGroup)
Initialize the filter.
Definition: xmltransformerproc.cpp:65
XmlTransformerProc::XmlTransformerProc
XmlTransformerProc(QObject *parent, const QVariantList &args)
Constructor.
Definition: xmltransformerproc.cpp:49
XmlTransformerProc::supportsAsync
virtual bool supportsAsync()
Returns True if the plugin supports asynchronous processing, i.e., supports asyncConvert method...
Definition: xmltransformerproc.cpp:90
xmltransformerproc.h
KttsFilterProc::fsIdle
Definition: filterproc.h:44
XmlTransformerProc::getOutput
virtual QString getOutput()
Returns the filtered output.
Definition: xmltransformerproc.cpp:320
KttsFilterProc::fsFiltering
Definition: filterproc.h:45
XmlTransformerProc::~XmlTransformerProc
virtual ~XmlTransformerProc()
Destructor.
Definition: xmltransformerproc.cpp:58
XmlTransformerProc::convert
virtual QString convert(const QString &inputText, TalkerCode *talkerCode, const QString &appId)
Convert input, returning output.
Definition: xmltransformerproc.cpp:101
XmlTransformerProc::stopFiltering
virtual void stopFiltering()
Stops filtering.
Definition: xmltransformerproc.cpp:335
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:32:25 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

jovie

Skip menu "jovie"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdeaccessibility API Reference

Skip menu "kdeaccessibility API Reference"
  • jovie

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