Code

change from <io.h> to <unistd.h> to define close
[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>
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)
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(), "xslt")) {
107             child_repr = sp_repr_children(child_repr);
108             while (child_repr != NULL) {
109                 if (!strcmp(child_repr->name(), "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;
128 void
129 XSLT::unload(Inkscape::Extension::Extension *module)
131     if (!module->loaded()) { return; }
132     xsltFreeStylesheet(_stylesheet);
133     xmlFreeDoc(_parsedDoc);
134     return;
137 SPDocument *
138 XSLT::open(Inkscape::Extension::Input *module, gchar const *filename)
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);
148     
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;
182 void
183 XSLT::save(Inkscape::Extension::Output *module, SPDocument *doc, gchar const *filename)
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 = Glib::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;
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 :