2023-04-27 Fred Gleason <fredg@paravelsystems.com>

* Removed a 'RDFeed::generateReport()' methods.
	* Added a 'DownloadRss()' method to the WebAPI.
	* Added a 'RDXsltEngine' class.
	* Added a 'Generate Front Report' item to the right-click menu in
	the 'Podcast Feeds' list in the 'Rivendell Feed List' dialog in
	rdadmin(1).
	* Added a 'Generate Back Report' item to the right-click menu in
	the 'Podcast Feeds' list in the 'Rivendell Feed List' dialog in
	rdadmin(1).

Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
Fred Gleason
2023-04-27 16:55:54 -04:00
parent 23b011cc93
commit 3cf2fe1ce4
22 changed files with 828 additions and 64 deletions

View File

@@ -2,7 +2,7 @@
##
## Automake.am for rivendell/lib
##
## (C) Copyright 2002-2022 Fred Gleason <fredg@paravelsystems.com>
## (C) Copyright 2002-2023 Fred Gleason <fredg@paravelsystems.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License version 2 as
@@ -136,6 +136,7 @@ dist_librd_la_SOURCES = dbversion.h\
rdexport_settings_dialog.cpp rdexport_settings_dialog.h\
rdfeed.cpp rdfeed.h\
rdfeedlistmodel.cpp rdfeedlistmodel.h\
rdfeedlistview.cpp rdfeedlistview.h\
rdfontengine.cpp rdfontengine.h\
rdformpost.cpp rdformpost.h\
rdflacdecode.cpp rdflacdecode.h\
@@ -295,7 +296,8 @@ dist_librd_la_SOURCES = dbversion.h\
rdweb.cpp rdweb.h\
rdwebresult.cpp rdwebresult.h\
rdwidget.cpp rdwidget.h\
rdxport_interface.h
rdxport_interface.h\
rdxsltengine.cpp rdxsltengine.h
nodist_librd_la_SOURCES = moc_rdadd_cart.cpp\
@@ -346,6 +348,7 @@ nodist_librd_la_SOURCES = moc_rdadd_cart.cpp\
moc_rdexport_settings_dialog.cpp\
moc_rdfeed.cpp\
moc_rdfeedlistmodel.cpp\
moc_rdfeedlistview.cpp\
moc_rdframe.cpp\
moc_rdget_ath.cpp\
moc_rdgetpasswd.cpp\
@@ -440,7 +443,8 @@ nodist_librd_la_SOURCES = moc_rdadd_cart.cpp\
moc_rdwavedata_dialog.cpp\
moc_rdwavescene.cpp\
moc_rdwavewidget.cpp\
moc_rdwidget.cpp
moc_rdwidget.cpp\
moc_rdxsltengine.cpp
librd_la_LDFLAGS = -release $(VERSION)

View File

@@ -225,6 +225,7 @@ SOURCES += rdwavescene.cpp
SOURCES += rdwavewidget.cpp
SOURCES += rdweb.cpp
SOURCES += rdwidget.cpp
SOURCES += rdxsltengine.cpp
HEADERS += rd.h
HEADERS += rdadd_cart.h
@@ -417,6 +418,7 @@ HEADERS += rdwavescene.h
HEADERS += rdwavewidget.h
HEADERS += rdweb.h
HEADERS += rdwidget.h
HEADERS += rdxsltengine.h
TRANSLATIONS += librd_cs.ts
TRANSLATIONS += librd_de.ts

View File

@@ -22,6 +22,7 @@
#include <math.h>
#include <QMessageBox>
#include <QProcess>
#include "rdapplication.h"
#include "rdaudioconvert.h"
@@ -57,7 +58,7 @@ int __RDFeed_Debug_Callback(CURL *handle,curl_infotype type,char *data,
}
size_t __RDFeed_Write_Callback(char *ptr,size_t size,size_t nmemb,
size_t __RDFeed_Download_Callback(char *ptr,size_t size,size_t nmemb,
void *userdata)
{
QByteArray *buffer=(QByteArray *)userdata;
@@ -868,7 +869,7 @@ bool RDFeed::postPodcast(unsigned cast_id,QString *err_msg)
}
QStringList *err_msgs=SetupCurlLogging(curl);
QByteArray write_buffer;
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,__RDFeed_Write_Callback);
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,__RDFeed_Download_Callback);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,&write_buffer);
curl_easy_setopt(curl,CURLOPT_HTTPPOST,first);
curl_easy_setopt(curl,CURLOPT_USERAGENT,
@@ -955,6 +956,90 @@ QString RDFeed::imageUrl(int img_id) const
}
bool RDFeed::downloadXml(QByteArray *xml,QString *err_msg)
{
long response_code;
CURL *curl=NULL;
CURLcode curl_err;
char curl_errorbuffer[CURL_ERROR_SIZE];
struct curl_httppost *first=NULL;
struct curl_httppost *last=NULL;
//
// Generate POST Data
//
curl_formadd(&first,&last,CURLFORM_PTRNAME,"COMMAND",
CURLFORM_COPYCONTENTS,
QString::asprintf("%u",RDXPORT_COMMAND_DOWNLOAD_RSS).toUtf8().
constData(),
CURLFORM_END);
curl_formadd(&first,&last,CURLFORM_PTRNAME,"LOGIN_NAME",
CURLFORM_COPYCONTENTS,rda->user()->name().toUtf8().constData(),
CURLFORM_END);
curl_formadd(&first,&last,CURLFORM_PTRNAME,"PASSWORD",
CURLFORM_COPYCONTENTS,
rda->user()->password().toUtf8().constData(),CURLFORM_END);
curl_formadd(&first,&last,CURLFORM_PTRNAME,"ID",
CURLFORM_COPYCONTENTS,
QString::asprintf("%u",feed_id).toUtf8().constData(),
CURLFORM_END);
//
// Set up the transfer
//
if((curl=curl_easy_init())==NULL) {
curl_formfree(first);
return false;
}
QStringList *err_msgs=SetupCurlLogging(curl);
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,__RDFeed_Download_Callback);
feed_xml.clear();
curl_easy_setopt(curl,CURLOPT_WRITEDATA,xml);
curl_easy_setopt(curl,CURLOPT_HTTPPOST,first);
curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,curl_errorbuffer);
curl_easy_setopt(curl,CURLOPT_USERAGENT,
rda->config()->userAgent().toUtf8().constData());
curl_easy_setopt(curl,CURLOPT_TIMEOUT,RD_CURL_TIMEOUT);
curl_easy_setopt(curl,CURLOPT_NOPROGRESS,1);
curl_easy_setopt(curl,CURLOPT_URL,
rda->station()->webServiceUrl(rda->config()).toUtf8().constData());
rda->syslog(LOG_DEBUG,"using web service URL: %s",
rda->station()->webServiceUrl(rda->config()).toUtf8().constData());
//
// Send it
//
if((curl_err=curl_easy_perform(curl))!=CURLE_OK) {
*err_msg=QString::fromUtf8(curl_errorbuffer);
curl_easy_cleanup(curl);
curl_formfree(first);
ProcessCurlLogging("RDFeed::postPodcast()",err_msgs);
return false;
}
//
// Clean up
//
curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&response_code);
curl_easy_cleanup(curl);
curl_formfree(first);
//
// Process the results
//
if((response_code<200)||(response_code>299)) {
*err_msg=tr("remote server returned unexpected response code")+
QString::asprintf(" %ld",response_code);
ProcessCurlLogging("RDFeed::postPodcast()",err_msgs);
return false;
}
delete err_msgs;
return true;
}
bool RDFeed::postXml(QString *err_msg)
{
long response_code;
@@ -1873,39 +1958,6 @@ QString RDFeed::itunesCategoryXml(const QString &category,
}
bool RDFeed::generateReport(const QString &feed_url,
const QString &stylesheet_pathname,
const QString &report_filename,
RDTempDirectory *tempdir,
QString *err_msg)
{
QString err_msg2;
int result;
bool ret=false;
ret=tempdir->create(&err_msg2);
if(ret) {
*err_msg=QObject::tr("Unable to create temporary directory.")+
"["+err_msg2+"]";
QString tmpfile=tempdir->path()+"/"+report_filename;
QString cmd="curl -f -s "+feed_url+" | xsltproc --encoding utf-8 "+
stylesheet_pathname+" - > "+tmpfile;
result=system(cmd.toUtf8());
if(result==-1) {
*err_msg=tr("unable to fork process")+" ["+strerror(errno)+"].";
return false;
}
if(WEXITSTATUS(result)!=0) {
*err_msg=tr("converter returned non-zero exit code.");
return false;
}
RDWebBrowser("file://"+tmpfile);
}
return ret;
}
void RDFeed::renderMessage(const QString &msg)
{
fprintf(stderr,"RENDERER: %s\n",msg.toUtf8().constData());
@@ -1962,7 +2014,7 @@ bool RDFeed::SavePodcast(unsigned cast_id,const QString &src_filename,
}
QStringList *err_msgs=SetupCurlLogging(curl);
QByteArray write_buffer;
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,__RDFeed_Write_Callback);
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,__RDFeed_Download_Callback);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,&write_buffer);
curl_easy_setopt(curl,CURLOPT_HTTPPOST,first);
curl_easy_setopt(curl,CURLOPT_USERAGENT,

View File

@@ -136,11 +136,12 @@ class RDFeed : public QObject
bool postPodcast(unsigned cast_id,QString *err_msg);
QString audioUrl(unsigned cast_id);
QString imageUrl(int img_id) const;
bool postXml(QString *err_msg);
bool downloadXml(QByteArray *xml,QString *err_msg); // WebAPI Call
bool postXml(QString *err_msg); // WebAPI Call
bool postXmlConditional(const QString &caption,QWidget *widget);
bool removeRss();
bool postImage(int img_id) const;
bool removeImage(int img_id) const;
bool removeRss(); // WebAPI Call
bool postImage(int img_id) const; // WebAPI Call
bool removeImage(int img_id) const; // WebAPI Call
void removeAllImages();
unsigned postCut(const QString &cutname,QString *err_msg);
unsigned postFile(const QString &srcfile,QString *err_msg);
@@ -154,10 +155,24 @@ class RDFeed : public QObject
static QString publicUrl(const QString &base_url,const QString &keyname);
static QString itunesCategoryXml(const QString &category,
const QString &sub_category,int padding=0);
/*
static bool generateReport(const QString &feed_url,
const QString &stylesheet_pathname,
const QString &report_filename,
RDTempDirectory *tempdir,QString *err_msg);
*/
/*
static bool generateReport(const QByteArray &src_xml,
const QString &stylesheet_pathname,
const QString &report_filename,
RDTempDirectory *tempdir,QString *err_msg);
*/
/*
static bool generateReport(QString *output,
const QString &src_xml,
const QString &stylesheet_pathname,
QString *err_msg);
*/
signals:
void postProgressChanged(int step);

View File

@@ -258,6 +258,12 @@ bool RDFeedListModel::isCast(const QModelIndex &index) const
}
QString RDFeedListModel::keyName(int row) const
{
return d_key_names.at(row);
}
QString RDFeedListModel::keyName(const QModelIndex &index) const
{
if(index.isValid()) {

View File

@@ -54,6 +54,7 @@ class RDFeedListModel : public QAbstractItemModel
bool isFeed(const QModelIndex &index) const;
bool isCast(const QModelIndex &index) const;
QString keyName(const QModelIndex &index) const;
QString keyName(int row) const;
unsigned feedId(const QModelIndex &index) const;
QString publicUrl(const QModelIndex &index) const;
QModelIndex feedRow(const QString &keyname) const;

131
lib/rdfeedlistview.cpp Normal file
View File

@@ -0,0 +1,131 @@
// rdfeedlistview.cpp
//
// RDTableView widget for RSS feeds
//
// (C) Copyright 2021 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include <QDragEnterEvent>
#include <QHeaderView>
#include <QMessageBox>
#include "rdfeed.h"
#include "rdfeedlistmodel.h"
#include "rdfeedlistview.h"
#include "rdtextfile.h"
RDFeedListView::RDFeedListView(QWidget *parent)
:RDTableView(parent)
{
d_mouse_row=-1;
//
// Mouse menu
//
d_mouse_menu=new QMenu(this);
d_front_report_action=d_mouse_menu->
addAction(tr("Generate Front Report"),this,SLOT(generateFrontReportData()));
d_front_report_action->setCheckable(false);
d_back_report_action=d_mouse_menu->
addAction(tr("Generate Back Report"),this,SLOT(generateBackReportData()));
d_back_report_action->setCheckable(false);
connect(d_mouse_menu,SIGNAL(aboutToShow()),
this,SLOT(aboutToShowMenuData()));
//
// XSLT Engine (for feed reports)
//
d_xslt_engine=
new RDXsltEngine("/usr/share/rivendell/rdcastmanager-report.xsl",this);
}
RDFeedListView::~RDFeedListView()
{
delete d_xslt_engine;
}
void RDFeedListView::aboutToShowMenuData()
{
RDFeedListModel *mod=(RDFeedListModel *)model();
if((d_mouse_row<0)||(d_mouse_row>=mod->rowCount())) {
d_front_report_action->setEnabled(false);
d_back_report_action->setEnabled(false);
}
else {
d_front_report_action->setEnabled(true);
d_back_report_action->setEnabled(true);
}
}
void RDFeedListView::generateFrontReportData()
{
QString err_msg;
RDFeedListModel *m=(RDFeedListModel *)model();
QString keyname=m->data(m->index(d_mouse_row,0)).toString();
RDFeed *feed=new RDFeed(keyname,rda->config(),this);
QByteArray xml;
if(feed->downloadXml(&xml,&err_msg)) {
QString output_filename="report.html";
if(d_xslt_engine->transformXml(&output_filename,xml,&err_msg)) {
RDWebBrowser("file://"+output_filename);
}
else {
QMessageBox::warning(this,"RDAdmin - "+tr("Error"),err_msg);
}
}
else {
QMessageBox::warning(this,"RDAdmin - "+tr("Error"),err_msg);
}
}
void RDFeedListView::generateBackReportData()
{
QString err_msg;
RDFeedListModel *m=(RDFeedListModel *)model();
QString url=m->data(m->index(d_mouse_row,6)).toString();
QString output_filename="report.html";
if(d_xslt_engine->transformUrl(&output_filename,url,&err_msg)) {
RDWebBrowser("file://"+output_filename);
}
else {
QMessageBox::warning(this,"RDAdmin - "+tr("Error"),err_msg);
return;
}
}
void RDFeedListView::mousePressEvent(QMouseEvent *e)
{
if(e->button()==Qt::RightButton) {
d_mouse_row=indexAt(e->pos()).row();
if((d_mouse_row>=0)&&(d_mouse_row<model()->rowCount())) {
d_mouse_menu->popup(e->globalPos());
}
else {
d_mouse_row=-1;
}
}
QTableView::mousePressEvent(e);
}

56
lib/rdfeedlistview.h Normal file
View File

@@ -0,0 +1,56 @@
// rdfeedlistview.h
//
// RDTableView widget for RSS feeds
//
// (C) Copyright 2023 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef RDFEEDLISTVIEW_H
#define RDFEEDLISTVIEW_H
#include <QAction>
#include <QList>
#include <QMenu>
#include <rdtableview.h>
#include <rdtempdirectory.h>
#include "rdxsltengine.h"
class RDFeedListView : public RDTableView
{
Q_OBJECT
public:
RDFeedListView(QWidget *parent=0);
~RDFeedListView();
private slots:
void aboutToShowMenuData();
void generateFrontReportData();
void generateBackReportData();
protected:
void mousePressEvent(QMouseEvent *e);
private:
int d_mouse_row;
QMenu *d_mouse_menu;
QAction *d_front_report_action;
QAction *d_back_report_action;
RDXsltEngine *d_xslt_engine;
};
#endif // RDFEEDLISTVIEW_H

View File

@@ -66,6 +66,7 @@
#define RDXPORT_COMMAND_REMOVE_RSS 43
#define RDXPORT_COMMAND_POST_IMAGE 44
#define RDXPORT_COMMAND_REMOVE_IMAGE 45
#define RDXPORT_COMMAND_DOWNLOAD_RSS 46
#endif // RDXPORT_INTERFACE_H

199
lib/rdxsltengine.cpp Normal file
View File

@@ -0,0 +1,199 @@
// rdxsltengine.cpp
//
// Engine for performing XSLT transformations
//
// (C) Copyright 2023 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include <curl/curl.h>
#include <QProcess>
#include <QStringList>
#include "rdapplication.h"
#include "rdxsltengine.h"
size_t __RDXsltEngine_Download_Callback(char *ptr,size_t size,size_t nmemb,
void *userdata)
{
QByteArray *buffer=(QByteArray *)userdata;
buffer->append(QByteArray(ptr,size*nmemb));
return size*nmemb;
}
RDXsltEngine::RDXsltEngine(const QString stylesheet_pathname,QObject *parent)
: QObject(parent)
{
d_stylesheet_pathname=stylesheet_pathname;
}
RDXsltEngine::~RDXsltEngine()
{
for(int i=0;i<d_temp_directories.size();i++) {
delete d_temp_directories.at(i);
}
}
QString RDXsltEngine::stylesheetPathname() const
{
return d_stylesheet_pathname;
}
bool RDXsltEngine::transformUrl(QString *output_filename,const QString &url,
QString *err_msg)
{
QString err_msg2;
bool ret=false;
CURL *curl=NULL;
CURLcode curl_err;
long response_code;
FILE *f=NULL;
d_temp_directories.push_back(new RDTempDirectory("rivendell-rdxslt"));
ret=d_temp_directories.back()->create(&err_msg2);
if(ret) {
// Download the source
if((curl=curl_easy_init())==NULL) {
*err_msg=tr("Unable to initialize CURL");
return false;
}
QByteArray src_xml;
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,__RDXsltEngine_Download_Callback);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,&src_xml);
curl_easy_setopt(curl,CURLOPT_USERAGENT,
rda->config()->userAgent().toUtf8().constData());
curl_easy_setopt(curl,CURLOPT_TIMEOUT,RD_CURL_TIMEOUT);
curl_easy_setopt(curl,CURLOPT_NOPROGRESS,1);
curl_easy_setopt(curl,CURLOPT_URL,url.toUtf8().constData());
curl_err=curl_easy_perform(curl);
if((ret=(curl_err==CURLE_OK))) {
curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&response_code);
if((ret=(response_code>=200)&&(response_code<300))) {
// Generate the report
QString output;
RDXsltEngine *xslt=new RDXsltEngine(d_stylesheet_pathname);
// ret=RDFeed::generateReport(&output,src_xml,stylesheet_pathname,err_msg);
ret=xslt->transform(&output,src_xml,err_msg);
if(ret) {
*output_filename=
d_temp_directories.last()->path()+"/"+*output_filename;
if((f=fopen((*output_filename).toUtf8(),"w"))!=NULL) {
fprintf(f,"%s",output.toUtf8().constData());
fclose(f);
}
else {
*err_msg=tr("Unable to create output file")+" ["+
strerror(errno)+"].";
}
}
}
}
else {
*err_msg=QObject::tr("Curl error")+" ["+curl_easy_strerror(curl_err)+"].";
curl_easy_cleanup(curl);
}
curl_easy_cleanup(curl);
}
else {
*err_msg=QObject::tr("Unable to create temporary directory.")+
" ["+err_msg2+"]";
}
return ret;
}
bool RDXsltEngine::transformXml(QString *output_filename,const QString &src_xml,
QString *err_msg)
{
QString err_msg2;
FILE *f=NULL;
bool ret=false;
QString output;
d_temp_directories.push_back(new RDTempDirectory("rivendell-rdxslt"));
ret=d_temp_directories.back()->create(&err_msg2);
if(ret) {
*output_filename=d_temp_directories.last()->path()+"/"+*output_filename;
ret=transform(&output,src_xml,err_msg);
if(ret) {
if((f=fopen((*output_filename).toUtf8(),"w"))!=NULL) {
fprintf(f,"%s",output.toUtf8().constData());
fclose(f);
}
else {
*err_msg=tr("Unable to create output file")+" ["+strerror(errno)+"].";
}
}
}
else {
*err_msg=QObject::tr("Unable to create temporary directory.")+
"["+err_msg2+"]";
}
return ret;
}
bool RDXsltEngine::transform(QString *output,const QString &src_xml,QString *err_msg)
{
QStringList args;
QProcess *proc=NULL;
args.push_back("--encoding");
args.push_back("utf-8");
args.push_back(d_stylesheet_pathname);
args.push_back("-");
proc=new QProcess(this);
proc->start("xsltproc",args);
if(!proc->waitForStarted()) {
*err_msg=tr("unable to start xsltproc(1)");
delete proc;
return false;
}
proc->write(src_xml.toUtf8());
proc->closeWriteChannel();
if(!proc->waitForFinished()) {
*err_msg=tr("xsltproc(1) is apparently hung!");
proc->kill();
delete proc;
return false;
}
if(proc->exitStatus()!=QProcess::NormalExit) {
*err_msg=tr("xsltproc(1) crashed!");
delete proc;
return false;
}
if(proc->exitCode()!=0) {
*err_msg=tr("xsltproc(1) returned an error")+" ["+
proc->readAllStandardError()+"].";
delete proc;
return false;
}
*output=QString::fromUtf8(proc->readAllStandardOutput());
delete proc;
return true;
}

48
lib/rdxsltengine.h Normal file
View File

@@ -0,0 +1,48 @@
// rdxsltengine.h
//
// Engine for performing XSLT transformations
//
// (C) Copyright 2023 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef RDXSLTENGINE_H
#define RDXSLTENGINE_H
#include <QList>
#include <QObject>
#include <rdtempdirectory.h>
class RDXsltEngine : public QObject
{
Q_OBJECT;
public:
RDXsltEngine(const QString stylesheet_pathname,QObject *parent=0);
~RDXsltEngine();
QString stylesheetPathname() const;
bool transformUrl(QString *output_filename,const QString &url,
QString *err_msg);
bool transformXml(QString *output_filename,const QString &src_xml,
QString *err_msg);
bool transform(QString *output,const QString &src_xml,QString *err_msg);
private:
QList<RDTempDirectory *> d_temp_directories;
QString d_stylesheet_pathname;
};
#endif // RDXSLTENGINE_H