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>
26 #include <libxml/parser.h>
27 #include <libxslt/transform.h>
29 Inkscape::XML::Document * sp_repr_do_read (xmlDocPtr doc, const gchar * default_ns);
31 /* Namespaces */
32 namespace Inkscape {
33 namespace Extension {
34 namespace Implementation {
36 /* Real functions */
37 /**
38 \return A XSLT object
39 \brief This function creates a XSLT object and sets up the
40 variables.
42 */
43 XSLT::XSLT(void) :
44 Implementation(),
45 _filename(""),
46 _parsedDoc(NULL),
47 _stylesheet(NULL)
48 {
49 }
51 Glib::ustring
52 XSLT::solve_reldir(Inkscape::XML::Node *reprin) {
54 gchar const *s = reprin->attribute("reldir");
56 if (!s) {
57 Glib::ustring str = sp_repr_children(reprin)->content();
58 return str;
59 }
61 Glib::ustring reldir = s;
63 if (reldir == "extensions") {
65 for (unsigned int i=0;
66 i < Inkscape::Extension::Extension::search_path.size();
67 i++) {
69 gchar * fname = g_build_filename(
70 Inkscape::Extension::Extension::search_path[i],
71 sp_repr_children(reprin)->content(),
72 NULL);
73 Glib::ustring filename = fname;
74 g_free(fname);
76 if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) )
77 return filename;
79 }
80 } else {
81 Glib::ustring str = sp_repr_children(reprin)->content();
82 return str;
83 }
85 return "";
86 }
88 bool
89 XSLT::check(Inkscape::Extension::Extension *module)
90 {
91 if (load(module)) {
92 unload(module);
93 return true;
94 } else {
95 return false;
96 }
97 }
99 bool
100 XSLT::load(Inkscape::Extension::Extension *module)
101 {
102 if (module->loaded()) { return true; }
104 Inkscape::XML::Node *child_repr = sp_repr_children(module->get_repr());
105 while (child_repr != NULL) {
106 if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "xslt")) {
107 child_repr = sp_repr_children(child_repr);
108 while (child_repr != NULL) {
109 if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "file")) {
110 _filename = solve_reldir(child_repr);
111 }
112 child_repr = sp_repr_next(child_repr);
113 }
115 break;
116 }
117 child_repr = sp_repr_next(child_repr);
118 }
120 _parsedDoc = xmlParseFile(_filename.c_str());
121 if (_parsedDoc == NULL) { return false; }
123 _stylesheet = xsltParseStylesheetDoc(_parsedDoc);
125 return true;
126 }
128 void
129 XSLT::unload(Inkscape::Extension::Extension *module)
130 {
131 if (!module->loaded()) { return; }
132 xsltFreeStylesheet(_stylesheet);
133 xmlFreeDoc(_parsedDoc);
134 return;
135 }
137 SPDocument *
138 XSLT::open(Inkscape::Extension::Input */*module*/, gchar const *filename)
139 {
140 xmlDocPtr filein = xmlParseFile(filename);
141 if (filein == NULL) { return NULL; }
143 const char * params[1];
144 params[0] = NULL;
146 xmlDocPtr result = xsltApplyStylesheet(_stylesheet, filein, params);
147 xmlFreeDoc(filein);
149 Inkscape::XML::Document * rdoc = sp_repr_do_read( result, SP_SVG_NS_URI);
150 xmlFreeDoc(result);
152 if (rdoc == NULL) {
153 return NULL;
154 }
156 if (strcmp(rdoc->root()->name(), "svg:svg") != 0) {
157 return NULL;
158 }
160 gchar * base = NULL;
161 gchar * name = NULL;
162 gchar * s = NULL, * p = NULL;
163 s = g_strdup(filename);
164 p = strrchr(s, '/');
165 if (p) {
166 name = g_strdup(p + 1);
167 p[1] = '\0';
168 base = g_strdup(s);
169 } else {
170 base = NULL;
171 name = g_strdup(filename);
172 }
173 g_free(s);
175 SPDocument * doc = sp_document_create(rdoc, filename, base, name, true);
177 g_free(base); g_free(name);
179 return doc;
180 }
182 void
183 XSLT::save(Inkscape::Extension::Output */*module*/, SPDocument *doc, gchar const *filename)
184 {
185 g_return_if_fail(doc != NULL);
186 g_return_if_fail(filename != NULL);
188 Inkscape::XML::Node *repr = NULL;
189 repr = sp_document_repr_root (doc);
191 gchar *save_path = g_path_get_dirname (filename);
192 Inkscape::IO::fixupHrefs( doc, save_path, true );
193 g_free(save_path);
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 gboolean const s = sp_repr_save_file (repr->document(), tempfilename_out.c_str(), SP_SVG_NS_URI);
205 if (s == FALSE) {
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;
225 }
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:encoding=utf-8:textwidth=99 :