Code

Indent support for XSLT extensions output.
[inkscape.git] / src / extension / implementation / xslt.cpp
1 /** \file
2  * Code for handling XSLT extensions.
3  */
4 /*
5  * Authors:
6  *   Ted Gould <ted@gould.cx>
7  *   Jon A. Cruz <jon@joncruz.org>
8  *   Abhishek Sharma
9  *
10  * Copyright (C) 2006-2007 Authors
11  *
12  * Released under GNU GPL, read the file 'COPYING' for more information
13  */
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
19 #include "xslt.h"
20 #include "../extension.h"
21 #include "../output.h"
23 #include "xml/repr.h"
24 #include "io/sys.h"
25 #include "file.h"
26 #include <unistd.h>
27 #include <cstring>
28 #include "document.h"
30 #include <libxml/parser.h>
31 #include <libxslt/transform.h>
32 #include <libxslt/xsltutils.h>
34 Inkscape::XML::Document * sp_repr_do_read (xmlDocPtr doc, const gchar * default_ns);
36 /* Namespaces */
37 namespace Inkscape {
38 namespace Extension {
39 namespace Implementation {
41 /* Real functions */
42 /**
43     \return    A XSLT object
44     \brief     This function creates a XSLT object and sets up the
45                variables.
47 */
48 XSLT::XSLT(void) :
49     Implementation(),
50     _filename(""),
51     _parsedDoc(NULL),
52     _stylesheet(NULL)
53 {
54 }
56 Glib::ustring
57 XSLT::solve_reldir(Inkscape::XML::Node *reprin) {
59     gchar const *s = reprin->attribute("reldir");
61     if (!s) {
62         Glib::ustring str = sp_repr_children(reprin)->content();
63         return str;
64     }
66     Glib::ustring reldir = s;
68     if (reldir == "extensions") {
70         for (unsigned int i=0;
71             i < Inkscape::Extension::Extension::search_path.size();
72             i++) {
74             gchar * fname = g_build_filename(
75                Inkscape::Extension::Extension::search_path[i],
76                sp_repr_children(reprin)->content(),
77                NULL);
78             Glib::ustring filename = fname;
79             g_free(fname);
81             if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) )
82                 return filename;
84         }
85     } else {
86         Glib::ustring str = sp_repr_children(reprin)->content();
87         return str;
88     }
90     return "";
91 }
93 bool
94 XSLT::check(Inkscape::Extension::Extension *module)
95 {
96     if (load(module)) {
97         unload(module);
98         return true;
99     } else {
100         return false;
101     }
104 bool
105 XSLT::load(Inkscape::Extension::Extension *module)
107     if (module->loaded()) { return true; }
109     Inkscape::XML::Node *child_repr = sp_repr_children(module->get_repr());
110     while (child_repr != NULL) {
111         if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "xslt")) {
112             child_repr = sp_repr_children(child_repr);
113             while (child_repr != NULL) {
114                 if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "file")) {
115                     _filename = solve_reldir(child_repr);
116                 }
117                 child_repr = sp_repr_next(child_repr);
118             }
120             break;
121         }
122         child_repr = sp_repr_next(child_repr);
123     }
125     _parsedDoc = xmlParseFile(_filename.c_str());
126     if (_parsedDoc == NULL) { return false; }
128     _stylesheet = xsltParseStylesheetDoc(_parsedDoc);
130     return true;
133 void
134 XSLT::unload(Inkscape::Extension::Extension *module)
136     if (!module->loaded()) { return; }
137     xsltFreeStylesheet(_stylesheet);
138     // No need to use xmlfreedoc(_parsedDoc), it's handled by xsltFreeStylesheet(_stylesheet);
139     return;
142 SPDocument *
143 XSLT::open(Inkscape::Extension::Input */*module*/, gchar const *filename)
145     xmlDocPtr filein = xmlParseFile(filename);
146     if (filein == NULL) { return NULL; }
148     const char * params[1];
149     params[0] = NULL;
151     xmlDocPtr result = xsltApplyStylesheet(_stylesheet, filein, params);
152     xmlFreeDoc(filein);
154     Inkscape::XML::Document * rdoc = sp_repr_do_read( result, SP_SVG_NS_URI);
155     xmlFreeDoc(result);
157     if (rdoc == NULL) {
158         return NULL;
159     }
161     if (strcmp(rdoc->root()->name(), "svg:svg") != 0) {
162         return NULL;
163     }
165     gchar * base = NULL;
166     gchar * name = NULL;
167     gchar * s = NULL, * p = NULL;
168     s = g_strdup(filename);
169     p = strrchr(s, '/');
170     if (p) {
171         name = g_strdup(p + 1);
172         p[1] = '\0';
173         base = g_strdup(s);
174     } else {
175         base = NULL;
176         name = g_strdup(filename);
177     }
178     g_free(s);
180     SPDocument * doc = SPDocument::createDoc(rdoc, filename, base, name, true);
182     g_free(base); g_free(name);
184     return doc;
187 void
188 XSLT::save(Inkscape::Extension::Output */*module*/, SPDocument *doc, gchar const *filename)
190     /* TODO: Should we assume filename to be in utf8 or to be a raw filename?
191      * See JavaFXOutput::save for discussion. */
192     g_return_if_fail(doc != NULL);
193     g_return_if_fail(filename != NULL);
195     Inkscape::XML::Node *repr = doc->getReprRoot();
197     std::string tempfilename_out;
198     int tempfd_out = 0;
199     try {
200         tempfd_out = Inkscape::IO::file_open_tmp(tempfilename_out, "ink_ext_XXXXXX");
201     } catch (...) {
202         /// \todo Popup dialog here
203         return;
204     }
206     if (!sp_repr_save_rebased_file(repr->document(), tempfilename_out.c_str(), SP_SVG_NS_URI,
207                                    doc->getBase(), filename)) {
208         throw Inkscape::Extension::Output::save_failed();
209     }
211     xmlDocPtr svgdoc = xmlParseFile(tempfilename_out.c_str());
212     close(tempfd_out);
213     if (svgdoc == NULL) {
214         return;
215     }
217     const char * params[1];
218     params[0] = NULL;
220     xmlDocPtr newdoc = xsltApplyStylesheet(_stylesheet, svgdoc, params);
221     //xmlSaveFile(filename, newdoc);
222     xsltSaveResultToFilename(filename, newdoc, _stylesheet, 0);
225     xmlFreeDoc(newdoc);
226     xmlFreeDoc(svgdoc);
228     xsltCleanupGlobals();
229     xmlCleanupParser();
231     return;
235 }  /* Implementation  */
236 }  /* module  */
237 }  /* Inkscape  */
240 /*
241   Local Variables:
242   mode:c++
243   c-file-style:"stroustrup"
244   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
245   indent-tabs-mode:nil
246   fill-column:99
247   End:
248 */
249 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :