xslt.cpp revision 0a06b01de629d811f25150dd5cf77401c1b6823c
2195N/A/** \file
2195N/A * Code for handling XSLT extensions.
2195N/A */
2195N/A/*
2195N/A * Authors:
2195N/A * Ted Gould <ted@gould.cx>
2195N/A *
2195N/A * Copyright (C) 2006-2007 Authors
2195N/A *
2195N/A * Released under GNU GPL, read the file 'COPYING' for more information
2195N/A */
2195N/A
2195N/A#ifdef HAVE_CONFIG_H
2195N/A# include <config.h>
2195N/A#endif
2195N/A
2195N/A#include "xslt.h"
2195N/A#include "../extension.h"
2195N/A#include "../output.h"
2195N/A
2195N/A#include "xml/repr.h"
2195N/A#include "io/sys.h"
2195N/A#include "file.h"
2195N/A
2195N/A#include <libxml/parser.h>
2195N/A#include <libxslt/transform.h>
2195N/A
2195N/AInkscape::XML::Document * sp_repr_do_read (xmlDocPtr doc, const gchar * default_ns);
2195N/A
2195N/A/* Namespaces */
2195N/Anamespace Inkscape {
2195N/Anamespace Extension {
2195N/Anamespace Implementation {
2195N/A
2195N/A/* Real functions */
2195N/A/**
2195N/A \return A XSLT object
2195N/A \brief This function creates a XSLT object and sets up the
2195N/A variables.
2195N/A
2195N/A*/
2195N/AXSLT::XSLT(void) :
2195N/A Implementation(),
2195N/A _filename(""),
2195N/A _parsedDoc(NULL),
2195N/A _stylesheet(NULL)
2195N/A{
2195N/A}
2195N/A
2195N/AGlib::ustring
2195N/AXSLT::solve_reldir(Inkscape::XML::Node *reprin) {
2195N/A
2195N/A gchar const *s = reprin->attribute("reldir");
2195N/A
2195N/A if (!s) {
2195N/A Glib::ustring str = sp_repr_children(reprin)->content();
2195N/A return str;
2195N/A }
2195N/A
2195N/A Glib::ustring reldir = s;
2195N/A
2195N/A if (reldir == "extensions") {
2195N/A
2195N/A for (unsigned int i=0;
2195N/A i < Inkscape::Extension::Extension::search_path.size();
2195N/A i++) {
2195N/A
2195N/A gchar * fname = g_build_filename(
2195N/A Inkscape::Extension::Extension::search_path[i],
2195N/A sp_repr_children(reprin)->content(),
2195N/A NULL);
2195N/A Glib::ustring filename = fname;
2195N/A g_free(fname);
2195N/A
2195N/A if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) )
2195N/A return filename;
2195N/A
2195N/A }
2195N/A } else {
2195N/A Glib::ustring str = sp_repr_children(reprin)->content();
2195N/A return str;
2195N/A }
2195N/A
2195N/A return "";
2195N/A}
2195N/A
2195N/Abool
2195N/AXSLT::check(Inkscape::Extension::Extension *module)
2195N/A{
2195N/A if (load(module)) {
2195N/A unload(module);
2195N/A return true;
2195N/A } else {
2195N/A return false;
2195N/A }
2195N/A}
2195N/A
2195N/Abool
2195N/AXSLT::load(Inkscape::Extension::Extension *module)
2195N/A{
2195N/A if (module->loaded()) { return true; }
2195N/A
2195N/A Inkscape::XML::Node *child_repr = sp_repr_children(module->get_repr());
2195N/A while (child_repr != NULL) {
2195N/A if (!strcmp(child_repr->name(), "xslt")) {
2195N/A child_repr = sp_repr_children(child_repr);
2195N/A while (child_repr != NULL) {
2195N/A if (!strcmp(child_repr->name(), "file")) {
_filename = solve_reldir(child_repr);
}
child_repr = sp_repr_next(child_repr);
}
break;
}
child_repr = sp_repr_next(child_repr);
}
_parsedDoc = xmlParseFile(_filename.c_str());
if (_parsedDoc == NULL) { return false; }
_stylesheet = xsltParseStylesheetDoc(_parsedDoc);
return true;
}
void
XSLT::unload(Inkscape::Extension::Extension *module)
{
if (!module->loaded()) { return; }
xsltFreeStylesheet(_stylesheet);
xmlFreeDoc(_parsedDoc);
return;
}
SPDocument *
XSLT::open(Inkscape::Extension::Input *module, gchar const *filename)
{
xmlDocPtr filein = xmlParseFile(filename);
if (filein == NULL) { return NULL; }
const char * params[1];
params[0] = NULL;
xmlDocPtr result = xsltApplyStylesheet(_stylesheet, filein, params);
xmlFreeDoc(filein);
Inkscape::XML::Document * rdoc = sp_repr_do_read( result, SP_SVG_NS_URI);
xmlFreeDoc(result);
if (rdoc == NULL) {
return NULL;
}
if (strcmp(rdoc->root()->name(), "svg:svg") != 0) {
return NULL;
}
gchar * base = NULL;
gchar * name = NULL;
gchar * s = NULL, * p = NULL;
s = g_strdup(filename);
p = strrchr(s, '/');
if (p) {
name = g_strdup(p + 1);
p[1] = '\0';
base = g_strdup(s);
} else {
base = NULL;
name = g_strdup(filename);
}
g_free(s);
SPDocument * doc = sp_document_create(rdoc, filename, base, name, true);
g_free(base); g_free(name);
return doc;
}
void
XSLT::save(Inkscape::Extension::Output *module, SPDocument *doc, gchar const *filename)
{
g_return_if_fail(doc != NULL);
g_return_if_fail(filename != NULL);
Inkscape::XML::Node *repr = NULL;
repr = sp_document_repr_root (doc);
gchar *save_path = g_path_get_dirname (filename);
Inkscape::IO::fixupHrefs( doc, save_path, true );
g_free(save_path);
std::string tempfilename_out;
int tempfd_out = 0;
try {
tempfd_out = Glib::file_open_tmp(tempfilename_out, "ink_ext_XXXXXX");
} catch (...) {
/// \todo Popup dialog here
return;
}
gboolean const s = sp_repr_save_file (repr->document(), tempfilename_out.c_str(), SP_SVG_NS_URI);
if (s == FALSE) {
throw Inkscape::Extension::Output::save_failed();
}
xmlDocPtr svgdoc = xmlParseFile(tempfilename_out.c_str());
close(tempfd_out);
if (svgdoc == NULL) {
return;
}
const char * params[1];
params[0] = NULL;
xmlDocPtr newdoc = xsltApplyStylesheet(_stylesheet, svgdoc, params);
xmlSaveFile(filename, newdoc);
xmlFreeDoc(newdoc);
xmlFreeDoc(svgdoc);
return;
}
} /* Implementation */
} /* module */
} /* Inkscape */
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :