Code

c929ba19a429c6e0062ea0daca978b9e2234b8c4
[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>
33 Inkscape::XML::Document * sp_repr_do_read (xmlDocPtr doc, const gchar * default_ns);
35 /* Namespaces */
36 namespace Inkscape {
37 namespace Extension {
38 namespace Implementation {
40 /* Real functions */
41 /**
42     \return    A XSLT object
43     \brief     This function creates a XSLT object and sets up the
44                variables.
46 */
47 XSLT::XSLT(void) :
48     Implementation(),
49     _filename(""),
50     _parsedDoc(NULL),
51     _stylesheet(NULL)
52 {
53 }
55 Glib::ustring
56 XSLT::solve_reldir(Inkscape::XML::Node *reprin) {
58     gchar const *s = reprin->attribute("reldir");
60     if (!s) {
61         Glib::ustring str = sp_repr_children(reprin)->content();
62         return str;
63     }
65     Glib::ustring reldir = s;
67     if (reldir == "extensions") {
69         for (unsigned int i=0;
70             i < Inkscape::Extension::Extension::search_path.size();
71             i++) {
73             gchar * fname = g_build_filename(
74                Inkscape::Extension::Extension::search_path[i],
75                sp_repr_children(reprin)->content(),
76                NULL);
77             Glib::ustring filename = fname;
78             g_free(fname);
80             if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) )
81                 return filename;
83         }
84     } else {
85         Glib::ustring str = sp_repr_children(reprin)->content();
86         return str;
87     }
89     return "";
90 }
92 bool
93 XSLT::check(Inkscape::Extension::Extension *module)
94 {
95     if (load(module)) {
96         unload(module);
97         return true;
98     } else {
99         return false;
100     }
103 bool
104 XSLT::load(Inkscape::Extension::Extension *module)
106     if (module->loaded()) { return true; }
108     Inkscape::XML::Node *child_repr = sp_repr_children(module->get_repr());
109     while (child_repr != NULL) {
110         if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "xslt")) {
111             child_repr = sp_repr_children(child_repr);
112             while (child_repr != NULL) {
113                 if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "file")) {
114                     _filename = solve_reldir(child_repr);
115                 }
116                 child_repr = sp_repr_next(child_repr);
117             }
119             break;
120         }
121         child_repr = sp_repr_next(child_repr);
122     }
124     _parsedDoc = xmlParseFile(_filename.c_str());
125     if (_parsedDoc == NULL) { return false; }
127     _stylesheet = xsltParseStylesheetDoc(_parsedDoc);
129     return true;
132 void
133 XSLT::unload(Inkscape::Extension::Extension *module)
135     if (!module->loaded()) { return; }
136     xsltFreeStylesheet(_stylesheet);
137     // No need to use xmlfreedoc(_parsedDoc), it's handled by xsltFreeStylesheet(_stylesheet);
138     return;
141 SPDocument *
142 XSLT::open(Inkscape::Extension::Input */*module*/, gchar const *filename)
144     xmlDocPtr filein = xmlParseFile(filename);
145     if (filein == NULL) { return NULL; }
147     const char * params[1];
148     params[0] = NULL;
150     xmlDocPtr result = xsltApplyStylesheet(_stylesheet, filein, params);
151     xmlFreeDoc(filein);
153     Inkscape::XML::Document * rdoc = sp_repr_do_read( result, SP_SVG_NS_URI);
154     xmlFreeDoc(result);
156     if (rdoc == NULL) {
157         return NULL;
158     }
160     if (strcmp(rdoc->root()->name(), "svg:svg") != 0) {
161         return NULL;
162     }
164     gchar * base = NULL;
165     gchar * name = NULL;
166     gchar * s = NULL, * p = NULL;
167     s = g_strdup(filename);
168     p = strrchr(s, '/');
169     if (p) {
170         name = g_strdup(p + 1);
171         p[1] = '\0';
172         base = g_strdup(s);
173     } else {
174         base = NULL;
175         name = g_strdup(filename);
176     }
177     g_free(s);
179     SPDocument * doc = SPDocument::createDoc(rdoc, filename, base, name, true);
181     g_free(base); g_free(name);
183     return doc;
186 void
187 XSLT::save(Inkscape::Extension::Output */*module*/, SPDocument *doc, gchar const *filename)
189     /* TODO: Should we assume filename to be in utf8 or to be a raw filename?
190      * See JavaFXOutput::save for discussion. */
191     g_return_if_fail(doc != NULL);
192     g_return_if_fail(filename != NULL);
194     Inkscape::XML::Node *repr = doc->getReprRoot();
196     std::string tempfilename_out;
197     int tempfd_out = 0;
198     try {
199         tempfd_out = Inkscape::IO::file_open_tmp(tempfilename_out, "ink_ext_XXXXXX");
200     } catch (...) {
201         /// \todo Popup dialog here
202         return;
203     }
205     if (!sp_repr_save_rebased_file(repr->document(), tempfilename_out.c_str(), SP_SVG_NS_URI,
206                                    doc->getBase(), filename)) {
207         throw Inkscape::Extension::Output::save_failed();
208     }
210     xmlDocPtr svgdoc = xmlParseFile(tempfilename_out.c_str());
211     close(tempfd_out);
212     if (svgdoc == NULL) {
213         return;
214     }
216     const char * params[1];
217     params[0] = NULL;
219     xmlDocPtr newdoc = xsltApplyStylesheet(_stylesheet, svgdoc, params);
220     xmlSaveFile(filename, newdoc);
222     xmlFreeDoc(newdoc);
223     xmlFreeDoc(svgdoc);
225     return;
229 }  /* Implementation  */
230 }  /* module  */
231 }  /* Inkscape  */
234 /*
235   Local Variables:
236   mode:c++
237   c-file-style:"stroustrup"
238   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
239   indent-tabs-mode:nil
240   fill-column:99
241   End:
242 */
243 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :