xslt_processorimpl.cpp [plain text]
#ifdef KHTML_XSLT
#include "xslt_processorimpl.h"
#include "xsl_stylesheetimpl.h"
#include "html_documentimpl.h"
#include "loader.h"
#include "khtmlview.h"
#include "khtml_part.h"
#include "KWQLoader.h"
#include <kio/job.h>
#include <libxslt/xsltutils.h>
#include <libxslt/documents.h>
#include <libxslt/imports.h>
using namespace khtml;
using namespace DOM;
namespace DOM {
XSLTProcessorImpl::XSLTProcessorImpl(XSLStyleSheetImpl* sheet, DocumentImpl* source)
:m_stylesheet(sheet), m_sourceDocument(source)
{
if (m_stylesheet)
m_stylesheet->ref();
if (m_sourceDocument)
m_sourceDocument->ref();
}
XSLTProcessorImpl::~XSLTProcessorImpl()
{
if (m_stylesheet)
m_stylesheet->deref();
if (m_sourceDocument)
m_sourceDocument->deref();
}
static void parseErrorFunc(void *ctxt, const char *msg, ...)
{
}
static XSLTProcessorImpl *globalProcessor = 0;
static xmlDocPtr stylesheetLoadFunc(const xmlChar* uri,
xmlDictPtr dict,
int options,
void* ctxt,
xsltLoadType type)
{
if (!globalProcessor)
return NULL;
switch (type) {
case XSLT_LOAD_DOCUMENT: {
KURL url = KURL((char *)uri);
KURL finalURL;
KIO::TransferJob *job = KIO::get(url, true, false);
QByteArray data;
QString headers;
xmlDocPtr doc;
xmlGenericErrorFunc oldErrorFunc = xmlGenericError;
void *oldErrorContext = xmlGenericErrorContext;
data = KWQServeSynchronousRequest(khtml::Cache::loader(),
globalProcessor->sourceDocument()->docLoader(), job, finalURL, headers);
xmlSetGenericErrorFunc(0, parseErrorFunc);
doc = xmlReadMemory(data.data(), data.size(), (const char *)uri, 0, options);
xmlSetGenericErrorFunc(oldErrorContext, oldErrorFunc);
return doc;
}
case XSLT_LOAD_STYLESHEET:
return globalProcessor->stylesheet()->locateStylesheetSubResource(((xsltStylesheetPtr)ctxt)->doc, uri);
default:
break;
}
return NULL;
}
DocumentImpl* XSLTProcessorImpl::transformDocument(DocumentImpl* doc)
{
m_resultOutput = "";
if (!m_stylesheet || !m_stylesheet->document()) return 0;
globalProcessor = this;
xsltSetLoaderFunc(stylesheetLoadFunc);
xsltStylesheetPtr sheet = m_stylesheet->compileStyleSheet();
if (!sheet) {
globalProcessor = 0;
xsltSetLoaderFunc(0);
return 0;
}
m_stylesheet->clearDocuments();
xmlDocPtr sourceDoc = (xmlDocPtr)doc->transformSource();
xmlDocPtr resultDoc = xsltApplyStylesheet(sheet, sourceDoc, NULL);
globalProcessor = 0;
xsltSetLoaderFunc(0);
DocumentImpl* result = documentFromXMLDocPtr(resultDoc, sheet);
xsltFreeStylesheet(sheet);
return result;
}
static int bufferWrite(void* context, const char* buffer, int len)
{
static_cast<XSLTProcessorImpl*>(context)->addToResult(buffer, len);
return len;
}
void XSLTProcessorImpl::addToResult(const char* buffer, int len)
{
m_resultOutput += QString::fromUtf8(buffer, len);
}
DocumentImpl *XSLTProcessorImpl::documentFromXMLDocPtr(xmlDocPtr resultDoc, xsltStylesheetPtr sheet)
{
if (!resultDoc || !sheet)
return 0;
DocumentImpl *result = 0;
xmlOutputBufferPtr outputBuf = xmlAllocOutputBuffer(NULL);
if (outputBuf) {
outputBuf->context = this;
outputBuf->writecallback = bufferWrite;
if (xsltSaveResultTo(outputBuf, resultDoc, sheet) < 0)
return 0;
KHTMLView *view = m_sourceDocument->view();
const xmlChar *method;
XSLT_GET_IMPORT_PTR(method, sheet, method);
if (method == NULL && resultDoc->type == XML_HTML_DOCUMENT_NODE)
method = (const xmlChar *)"html";
if (xmlStrEqual(method, (const xmlChar *)"html"))
result = m_sourceDocument->implementation()->createHTMLDocument(view);
else
result = m_sourceDocument->implementation()->createDocument(view);
result->attach();
result->setURL(m_sourceDocument->URL());
result->setBaseURL(m_sourceDocument->baseURL());
result->docLoader()->setShowAnimations(m_sourceDocument->docLoader()->showAnimations());
result->setTransformSourceDocument(m_sourceDocument);
if (xmlStrEqual(method, (const xmlChar *)"text")) {
m_resultOutput = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/strict.dtd\">\n"
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
"<body>\n"
"<pre>\n"
"<![CDATA[" + m_resultOutput + "]]>\n"
"</pre>\n"
"</body>\n"
"</html>\n";
}
if (view) {
view->clear();
view->part()->replaceDocImpl(result);
}
result->open();
result->determineParseMode(m_resultOutput); result->write(m_resultOutput);
result->finishParsing();
result->setParsing(false);
if (view)
view->part()->checkCompleted();
else
result->close(); }
return result;
}
}
#endif