Code

Pot and Dutch translation update
[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  *
8  * Copyright (C) 2006-2007 Authors
9  *
10  * Released under GNU GPL, read the file 'COPYING' for more information
11  */
13 #ifdef HAVE_CONFIG_H
14 # include <config.h>
15 #endif
17 #include "xslt.h"
18 #include "../extension.h"
19 #include "../output.h"
21 #include "xml/repr.h"
22 #include "io/sys.h"
23 #include "file.h"
24 #include <unistd.h>
25 #include <cstring>
26 #include "document.h"
28 #include <libxml/parser.h>
29 #include <libxslt/transform.h>
31 Inkscape::XML::Document * sp_repr_do_read (xmlDocPtr doc, const gchar * default_ns);
33 /* Namespaces */
34 namespace Inkscape {
35 namespace Extension {
36 namespace Implementation {
38 /* Real functions */
39 /**
40     \return    A XSLT object
41     \brief     This function creates a XSLT object and sets up the
42                variables.
44 */
45 XSLT::XSLT(void) :
46     Implementation(),
47     _filename(""),
48     _parsedDoc(NULL),
49     _stylesheet(NULL)
50 {
51 }
53 Glib::ustring
54 XSLT::solve_reldir(Inkscape::XML::Node *reprin) {
56     gchar const *s = reprin->attribute("reldir");
58     if (!s) {
59         Glib::ustring str = sp_repr_children(reprin)->content();
60         return str;
61     }
63     Glib::ustring reldir = s;
65     if (reldir == "extensions") {
67         for (unsigned int i=0;
68             i < Inkscape::Extension::Extension::search_path.size();
69             i++) {
71             gchar * fname = g_build_filename(
72                Inkscape::Extension::Extension::search_path[i],
73                sp_repr_children(reprin)->content(),
74                NULL);
75             Glib::ustring filename = fname;
76             g_free(fname);
78             if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) )
79                 return filename;
81         }
82     } else {
83         Glib::ustring str = sp_repr_children(reprin)->content();
84         return str;
85     }
87     return "";
88 }
90 bool
91 XSLT::check(Inkscape::Extension::Extension *module)
92 {
93     if (load(module)) {
94         unload(module);
95         return true;
96     } else {
97         return false;
98     }
99 }
101 bool
102 XSLT::load(Inkscape::Extension::Extension *module)
104     if (module->loaded()) { return true; }
106     Inkscape::XML::Node *child_repr = sp_repr_children(module->get_repr());
107     while (child_repr != NULL) {
108         if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "xslt")) {
109             child_repr = sp_repr_children(child_repr);
110             while (child_repr != NULL) {
111                 if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "file")) {
112                     _filename = solve_reldir(child_repr);
113                 }
114                 child_repr = sp_repr_next(child_repr);
115             }
117             break;
118         }
119         child_repr = sp_repr_next(child_repr);
120     }
122     _parsedDoc = xmlParseFile(_filename.c_str());
123     if (_parsedDoc == NULL) { return false; }
125     _stylesheet = xsltParseStylesheetDoc(_parsedDoc);
127     return true;
130 void
131 XSLT::unload(Inkscape::Extension::Extension *module)
133     if (!module->loaded()) { return; }
134     xsltFreeStylesheet(_stylesheet);
135     // No need to use xmlfreedoc(_parsedDoc), it's handled by xsltFreeStylesheet(_stylesheet);
136     return;
139 SPDocument *
140 XSLT::open(Inkscape::Extension::Input */*module*/, gchar const *filename)
142     xmlDocPtr filein = xmlParseFile(filename);
143     if (filein == NULL) { return NULL; }
145     const char * params[1];
146     params[0] = NULL;
148     xmlDocPtr result = xsltApplyStylesheet(_stylesheet, filein, params);
149     xmlFreeDoc(filein);
151     Inkscape::XML::Document * rdoc = sp_repr_do_read( result, SP_SVG_NS_URI);
152     xmlFreeDoc(result);
154     if (rdoc == NULL) {
155         return NULL;
156     }
158     if (strcmp(rdoc->root()->name(), "svg:svg") != 0) {
159         return NULL;
160     }
162     gchar * base = NULL;
163     gchar * name = NULL;
164     gchar * s = NULL, * p = NULL;
165     s = g_strdup(filename);
166     p = strrchr(s, '/');
167     if (p) {
168         name = g_strdup(p + 1);
169         p[1] = '\0';
170         base = g_strdup(s);
171     } else {
172         base = NULL;
173         name = g_strdup(filename);
174     }
175     g_free(s);
177     SPDocument * doc = sp_document_create(rdoc, filename, base, name, true);
179     g_free(base); g_free(name);
181     return doc;
184 void
185 XSLT::save(Inkscape::Extension::Output */*module*/, SPDocument *doc, gchar const *filename)
187     /* TODO: Should we assume filename to be in utf8 or to be a raw filename?
188      * See JavaFXOutput::save for discussion. */
189     g_return_if_fail(doc != NULL);
190     g_return_if_fail(filename != NULL);
192     Inkscape::XML::Node *repr = NULL;
193     repr = sp_document_repr_root (doc);
195     std::string tempfilename_out;
196     int tempfd_out = 0;
197     try {
198         tempfd_out = Inkscape::IO::file_open_tmp(tempfilename_out, "ink_ext_XXXXXX");
199     } catch (...) {
200         /// \todo Popup dialog here
201         return;
202     }
204     if (!sp_repr_save_rebased_file(repr->document(), tempfilename_out.c_str(), SP_SVG_NS_URI,
205                                    doc->base, filename)) {
206         throw Inkscape::Extension::Output::save_failed();
207     }
209     xmlDocPtr svgdoc = xmlParseFile(tempfilename_out.c_str());
210     close(tempfd_out);
211     if (svgdoc == NULL) {
212         return;
213     }
215     const char * params[1];
216     params[0] = NULL;
218     xmlDocPtr newdoc = xsltApplyStylesheet(_stylesheet, svgdoc, params);
219     xmlSaveFile(filename, newdoc);
221     xmlFreeDoc(newdoc);
222     xmlFreeDoc(svgdoc);
224     return;
228 }  /* Implementation  */
229 }  /* module  */
230 }  /* Inkscape  */
233 /*
234   Local Variables:
235   mode:c++
236   c-file-style:"stroustrup"
237   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
238   indent-tabs-mode:nil
239   fill-column:99
240   End:
241 */
242 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :