[gnote] ExportToHtml addin



commit 2b7b95076d3e540b711d836a857c13b583eddc0a
Author: Hubert Figuiere <hub figuiere net>
Date:   Tue May 12 00:41:45 2009 -0400

    ExportToHtml addin
---
 NEWS                                              |    2 +
 README                                            |    1 +
 configure.ac                                      |    2 +
 src/Makefile.am                                   |    3 +
 src/addins/Makefile.am                            |    1 +
 src/addins/exporttohtml/Makefile.am               |   22 ++
 src/addins/exporttohtml/exporttohtml.xsl          |  182 +++++++++++++
 src/addins/exporttohtml/exporttohtmldialog.cpp    |   96 +++++++
 src/addins/exporttohtml/exporttohtmldialog.hpp    |   53 ++++
 src/addins/exporttohtml/exporttohtmlnoteaddin.cpp |  280 +++++++++++++++++++++
 src/addins/exporttohtml/exporttohtmlnoteaddin.hpp |   79 ++++++
 src/addins/exporttohtml/notenameresolver.hpp      |   38 +++
 src/sharp/streamwriter.cpp                        |   71 ++++++
 src/sharp/streamwriter.hpp                        |   64 +++++
 src/sharp/uri.cpp                                 |    6 +
 src/sharp/uri.hpp                                 |    1 +
 src/sharp/xmlresolver.hpp                         |   43 ++++
 src/sharp/xmlwriter.cpp                           |    8 +
 src/sharp/xmlwriter.hpp                           |    3 +-
 src/sharp/xsltargumentlist.cpp                    |   69 +++++
 src/sharp/xsltargumentlist.hpp                    |   70 +++++
 src/sharp/xsltransform.cpp                        |   90 +++++++
 src/sharp/xsltransform.hpp                        |   63 +++++
 23 files changed, 1246 insertions(+), 1 deletions(-)

diff --git a/NEWS b/NEWS
index 22eac25..59be053 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,5 @@
+  * Addin to export to HTML.
+
 0.4.0 -
 
 New features:
diff --git a/README b/README
index bbb45dc..712a1d8 100644
--- a/README
+++ b/README
@@ -15,6 +15,7 @@ Dependencies:
 - Gtkmm 2.12 minimum (Gtkmm 2.14 recommended)
 - Gtk+ 2.12.
 - Libxml++ 2.6 or later (2.26 recommended)
+- libxslt
 - libuuid
 - boost 1.34
 - (optional) gtk-spell 2.0.9
diff --git a/configure.ac b/configure.ac
index e7819d1..2086a58 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,7 @@ PKG_CHECK_MODULES(LIBGLIBMM, [glibmm-2.4])
 PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= $GTK_VERSION])
 PKG_CHECK_MODULES(LIBGTKMM, [gtkmm-2.4 >= $LIBGTKMM_VERSION])
 PKG_CHECK_MODULES(LIBXML, [libxml-2.0])
+PKG_CHECK_MODULES(LIBXSLT, [libxslt])
 PKG_CHECK_MODULES(LIBXMLPP, [libxml++-2.6])
 PKG_CHECK_MODULES(GCONF, [gconf-2.0])
 dnl PKG_CHECK_MODULES(LIBGLADEMM, [libglademm-2.4 >= $LIBGLADEMM_VERSION])
@@ -210,6 +211,7 @@ src/addins/Makefile
 src/addins/addins.mk
 src/addins/backlinks/Makefile
 src/addins/bugzilla/Makefile
+src/addins/exporttohtml/Makefile
 src/addins/fixedwidth/Makefile
 src/addins/inserttimestamp/Makefile
 src/addins/printnotes/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 28c6056..f44326b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -72,11 +72,14 @@ libgnote_a_SOURCES = \
 	sharp/modulefactory.hpp \
 	sharp/modulemanager.hpp sharp/modulemanager.cpp \
 	sharp/propertyeditor.hpp sharp/propertyeditor.cpp \
+	sharp/streamwriter.hpp sharp/streamwriter.cpp \
 	sharp/string.hpp sharp/string.cpp \
 	sharp/uri.hpp sharp/uri.cpp \
 	sharp/uuid.hpp \
 	sharp/xmlconvert.hpp sharp/xmlconvert.cpp \
 	sharp/xmlwriter.hpp sharp/xmlwriter.cpp \
+	sharp/xsltargumentlist.hpp sharp/xsltargumentlist.cpp \
+	sharp/xsltransform.hpp sharp/xsltransform.cpp \
 	gnote.cpp gnote.hpp \
 	abstractaddin.hpp abstractaddin.cpp \
 	actionmanager.hpp actionmanager.cpp \
diff --git a/src/addins/Makefile.am b/src/addins/Makefile.am
index ba5989e..0306d8b 100644
--- a/src/addins/Makefile.am
+++ b/src/addins/Makefile.am
@@ -3,6 +3,7 @@
 
 SUBDIRS = backlinks \
 	bugzilla \
+	exporttohtml \
 	fixedwidth \
 	inserttimestamp \
 	printnotes \
diff --git a/src/addins/exporttohtml/Makefile.am b/src/addins/exporttohtml/Makefile.am
new file mode 100644
index 0000000..4c9c769
--- /dev/null
+++ b/src/addins/exporttohtml/Makefile.am
@@ -0,0 +1,22 @@
+
+include $(builddir)/../addins.mk
+
+
+INCLUDES = @LIBXSLT_CFLAGS@
+
+addinsdir = $(ADDINSDIR)
+addins_LTLIBRARIES = exporttohtml.la
+
+xsldir = @datadir@/gnote
+xsl_DATA = exporttohtml.xsl
+
+exporttohtml_la_LIBADD = @LIBXSLT_LIBS@
+
+exporttohtml_la_SOURCES = exporttohtmlnoteaddin.hpp exporttohtmlnoteaddin.cpp \
+	exporttohtmldialog.hpp exporttohtmldialog.cpp \
+	$(srcdir)/../../sharp/streamwriter.cpp \
+	$(srcdir)/../../sharp/xsltransform.cpp \
+	$(srcdir)/../../sharp/xsltargumentlist.cpp \
+	$(NULL)
+
+EXTRA_DIST = exporttohtml.xsl
diff --git a/src/addins/exporttohtml/exporttohtml.xsl b/src/addins/exporttohtml/exporttohtml.xsl
new file mode 100644
index 0000000..2e02c5d
--- /dev/null
+++ b/src/addins/exporttohtml/exporttohtml.xsl
@@ -0,0 +1,182 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
+		xmlns:tomboy="http://beatniksoftware.com/tomboy";
+		xmlns:size="http://beatniksoftware.com/tomboy/size";
+		xmlns:link="http://beatniksoftware.com/tomboy/link";
+                version='1.0'>
+
+<xsl:output method="html" indent="no" />
+<xsl:preserve-space elements="*" />
+
+<xsl:param name="font" />
+<xsl:param name="export-linked" />
+<xsl:param name="export-linked-all" />
+<xsl:param name="root-note" />
+
+<xsl:param name="newline" select="'&#xA;'" />
+
+<xsl:template match="/">
+	<html>
+	<head>
+	<title><xsl:value-of select="/tomboy:note/tomboy:title" /></title>
+	<style type="text/css">
+	body { <xsl:value-of select="$font" /> }
+	h1 { font-size: xx-large;
+     	     font-weight: bold;
+     	     border-bottom: 1px solid black; }
+	div.note {
+		   position: relative;
+		   display: block;
+		   padding: 5pt;
+		   margin: 5pt; 
+		   white-space: -moz-pre-wrap; /* Mozilla */
+ 	      	   white-space: -pre-wrap;     /* Opera 4 - 6 */
+ 	      	   white-space: -o-pre-wrap;   /* Opera 7 */
+ 	      	   white-space: pre-wrap;      /* CSS3 */
+ 	      	   word-wrap: break-word;      /* IE 5.5+ */ }
+	</style>
+	</head>
+	<body>
+
+	<xsl:apply-templates select="tomboy:note"/>
+
+	</body>
+	</html>
+</xsl:template>
+
+<xsl:template match="text()">
+   <xsl:call-template name="softbreak"/>
+</xsl:template>
+
+<xsl:template name="softbreak">
+	<xsl:param name="text" select="."/>
+	<xsl:choose>
+		<xsl:when test="contains($text, '&#x2028;')">
+			<xsl:value-of select="substring-before($text, '&#x2028;')"/>
+			<br/>
+			<xsl:call-template name="softbreak">
+				<xsl:with-param name="text" select="substring-after($text, '&#x2028;')"/>
+			</xsl:call-template>
+		</xsl:when>
+		
+		<xsl:otherwise>
+			<xsl:value-of select="$text"/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template match="tomboy:note">
+	<xsl:apply-templates select="tomboy:text"/>
+</xsl:template>
+
+<xsl:template match="tomboy:text">
+	<div class="note" 
+	     id="{/tomboy:note/tomboy:title}">
+		<a name="{tomboy:ToLower(/tomboy:note/tomboy:title)}" />
+		<xsl:apply-templates select="node()" />
+	</div>
+	
+	<xsl:if test="$export-linked and ((not($export-linked-all) and /tomboy:note/tomboy:title/text() = $root-note) or $export-linked-all)">
+		<xsl:for-each select=".//link:internal/text()">
+			<!-- Load in the linked note's XML for processing. -->
+			<xsl:apply-templates select="document(.)/node()"/>
+		</xsl:for-each>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template match="tomboy:note/tomboy:text/*[1]/text()[1]">
+	<h1><xsl:value-of select="substring-before(., $newline)"/></h1>
+	<xsl:value-of select="substring-after(., $newline)"/>
+</xsl:template>
+
+<xsl:template match="tomboy:bold">
+	<b><xsl:apply-templates select="node()"/></b>
+</xsl:template>
+
+<xsl:template match="tomboy:italic">
+	<i><xsl:apply-templates select="node()"/></i>
+</xsl:template>
+
+<xsl:template match="tomboy:strikethrough">
+	<strike><xsl:apply-templates select="node()"/></strike>
+</xsl:template>
+
+<xsl:template match="tomboy:highlight">
+	<span style="background:yellow"><xsl:apply-templates select="node()"/></span>
+</xsl:template>
+
+<xsl:template match="tomboy:datetime">
+	<span style="font-style:italic;font-size:small;color:#888A85">
+		<xsl:apply-templates select="node()"/>
+	</span>
+</xsl:template>
+
+<xsl:template match="size:small">
+	<span style="font-size:small"><xsl:apply-templates select="node()"/></span>
+</xsl:template>
+
+<xsl:template match="size:large">
+	<span style="font-size:large"><xsl:apply-templates select="node()"/></span>
+</xsl:template>
+
+<xsl:template match="size:huge">
+	<span style="font-size:xx-large"><xsl:apply-templates select="node()"/></span>
+</xsl:template>
+
+<xsl:template match="link:broken">
+	<span style="color:#555753;text-decoration:underline">
+		<xsl:value-of select="node()"/>
+	</span>
+</xsl:template>
+
+<xsl:template match="link:internal">
+	<a style="color:#204A87" href="#{tomboy:ToLower(node())}">
+		<xsl:value-of select="node()"/>
+	</a>
+</xsl:template>
+
+<xsl:template match="link:url">
+	<a style="color:#3465A4" href="{node()}"><xsl:value-of select="node()"/></a>
+</xsl:template>
+
+<xsl:template match="tomboy:list">
+	<ul>
+		<xsl:apply-templates select="tomboy:list-item" />
+	</ul>
+</xsl:template>
+
+<xsl:template match="tomboy:list-item">
+	<li>
+		<xsl:if test="normalize-space(text()) = ''">
+			<xsl:attribute name="style">list-style-type: none</xsl:attribute>
+		</xsl:if>
+		<xsl:attribute name="dir">
+			<xsl:value-of select="@dir"/>
+		</xsl:attribute>
+		<xsl:apply-templates select="node()" />
+	</li>
+</xsl:template>
+
+<!-- Evolution.dll Plugin -->
+<xsl:template match="link:evo-mail">
+	<a href="{./@uri}">
+		<img alt="Open Email Link" width="16" height="10" border="0">
+			<!-- Inline Base64 encoded stock_mail.png =) -->
+			<xsl:attribute name="src">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAKCAYAAAC9vt6cAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI WXMAAAsQAAALEAGtI711AAAAB3RJTUUH1QkeAjYaRAvZgAAAALxJREFUKM+NkjGKw1AMRN+GhRS/ 2xP4EHZr0E1UxFVuoiKdikCKfxMfwKdw+3t1gb/F4hASe50BgZjRDEII/jAAtWmaCnxSAy+oZlYj YrfMbAkB4GsJiAjcnfPpRNzvrCHnjIjQdd3De3geUFX8diMdj6tmVX3jD6+EquLXKz9p37waANC2 LRfPpJTIOdP3PXuoEVFLKdXMaills5+m6f8jbq26dcTvRXR3RIR5njcDRIRxHFe14cMHenukX9eX mbvfl0q9AAAAAElFTkSuQmCC</xsl:attribute>
+		</img>
+		<xsl:value-of select="node()"/>
+	</a>
+</xsl:template>
+
+<!-- FixedWidth.dll Plugin -->
+<xsl:template match="tomboy:monospace">
+	<span style="font-family:monospace"><xsl:apply-templates select="node()"/></span>
+</xsl:template>
+
+<!-- Bugzilla.dll Plugin -->
+<xsl:template match="link:bugzilla">
+	<a href="{ uri}"><xsl:value-of select="node()" /></a>
+</xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/src/addins/exporttohtml/exporttohtmldialog.cpp b/src/addins/exporttohtml/exporttohtmldialog.cpp
new file mode 100644
index 0000000..881d3b6
--- /dev/null
+++ b/src/addins/exporttohtml/exporttohtmldialog.cpp
@@ -0,0 +1,96 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+
+#include <glibmm/i18n.h>
+#include <gtkmm/stock.h>
+#include <gtkmm/table.h>
+
+#include "exporttohtmldialog.hpp"
+
+
+namespace exporttohtml {
+
+
+ExportToHtmlDialog::ExportToHtmlDialog(const std::string & default_file)
+  : Gtk::FileChooserDialog(_("Destination for HTML Export"),
+                           Gtk::FILE_CHOOSER_ACTION_SAVE)
+  , m_export_linked(_("Export linked notes"))
+  , m_export_linked_all(_("Include all other linked notes"))
+
+{
+  add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+  add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
+
+  set_default_response(Gtk::RESPONSE_OK);
+
+  Gtk::Table *table = manage(new Gtk::Table (2, 2, false));
+
+  m_export_linked.signal_toggled().connect(
+    sigc::mem_fun(*this, &ExportToHtmlDialog::on_export_linked_toggled));
+
+  table->attach (m_export_linked, 0, 2, 0, 1, Gtk::FILL, (Gtk::AttachOptions)0, 0, 0);
+  table->attach (m_export_linked_all,
+                 1, 2, 1, 2, Gtk::EXPAND | Gtk::FILL, (Gtk::AttachOptions)0, 20, 0);
+
+  set_extra_widget(*table);
+
+  set_do_overwrite_confirmation(true);
+  set_local_only(true);
+
+  show_all ();
+  load_preferences (default_file);
+}
+
+
+bool ExportToHtmlDialog::get_export_linked() const
+{
+  return m_export_linked.get_active();
+}
+
+bool ExportToHtmlDialog::get_export_linked_all() const
+{
+  return m_export_linked_all.get_active();
+}
+
+
+void ExportToHtmlDialog::save_preferences()
+{
+}
+
+
+void ExportToHtmlDialog::load_preferences(const std::string & )
+{
+}
+
+
+void ExportToHtmlDialog::on_export_linked_toggled()
+{
+  if (m_export_linked.get_active()) {
+    m_export_linked_all.set_sensitive(true);
+  }
+  else {
+    m_export_linked_all.set_sensitive(false);
+  }
+}
+
+
+
+}
diff --git a/src/addins/exporttohtml/exporttohtmldialog.hpp b/src/addins/exporttohtml/exporttohtmldialog.hpp
new file mode 100644
index 0000000..ea3cb4a
--- /dev/null
+++ b/src/addins/exporttohtml/exporttohtmldialog.hpp
@@ -0,0 +1,53 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __EXPORT_TO_HTML_DIALOG_HPP_
+#define __EXPORT_TO_HTML_DIALOG_HPP_
+
+#include <string>
+
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/filechooserdialog.h>
+
+
+namespace exporttohtml {
+
+class ExportToHtmlDialog
+  : public Gtk::FileChooserDialog
+{
+public:
+  ExportToHtmlDialog(const std::string &);
+  void save_preferences();
+
+  bool get_export_linked() const;
+  bool get_export_linked_all() const;
+
+private:
+  void on_export_linked_toggled();
+  void load_preferences(const std::string & );
+  Gtk::CheckButton m_export_linked;
+  Gtk::CheckButton m_export_linked_all;
+};
+
+
+}
+
+
+#endif
diff --git a/src/addins/exporttohtml/exporttohtmlnoteaddin.cpp b/src/addins/exporttohtml/exporttohtmlnoteaddin.cpp
new file mode 100644
index 0000000..1cd5544
--- /dev/null
+++ b/src/addins/exporttohtml/exporttohtmlnoteaddin.cpp
@@ -0,0 +1,280 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/format.hpp>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/xpathInternals.h>
+#include <libxslt/extensions.h>
+
+#include <glibmm/i18n.h>
+#include <gtkmm/stock.h>
+
+#include "sharp/exception.hpp"
+#include "sharp/streamwriter.hpp"
+#include "sharp/string.hpp"
+#include "sharp/uri.hpp"
+#include "sharp/xsltargumentlist.hpp"
+#include "debug.hpp"
+#include "preferences.hpp"
+#include "notewindow.hpp"
+#include "utils.hpp"
+
+#include "exporttohtmlnoteaddin.hpp"
+#include "exporttohtmldialog.hpp"
+#include "notenameresolver.hpp"
+
+#define STYLESHEET_NAME "exporttohtml.xsl"
+
+
+using gnote::Preferences;
+
+namespace exporttohtml {
+
+
+ExportToHtmlModule::ExportToHtmlModule()
+{
+  ADD_INTERFACE_IMPL(ExportToHtmlNoteAddin);
+}
+const char * ExportToHtmlModule::id() const
+{
+  return "ExportToHtmlAddin";
+}
+const char * ExportToHtmlModule::name() const
+{
+  return _("Export to HTML");
+}
+const char * ExportToHtmlModule::description() const
+{
+  return _("Exports individual notes to HTML.");
+}
+const char * ExportToHtmlModule::authors() const
+{
+  return _("Hubert Figuiere and the Tomboy Project");
+}
+const char * ExportToHtmlModule::category() const
+{
+  return "Tools";
+}
+const char * ExportToHtmlModule::version() const
+{
+  return "0.1";
+}
+
+sharp::XslTransform *ExportToHtmlNoteAddin::s_xsl = NULL;
+
+
+void ExportToHtmlNoteAddin::initialize()
+{
+  
+}
+
+
+void ExportToHtmlNoteAddin::shutdown()
+{
+}
+
+
+void ExportToHtmlNoteAddin::on_note_opened()
+{
+	Gtk::ImageMenuItem *item =  manage(new Gtk::ImageMenuItem (_("Export to HTML")));
+  item->set_image(*manage(new Gtk::Image (Gtk::Stock::SAVE, Gtk::ICON_SIZE_MENU)));
+  item->signal_activate().connect(
+    sigc::mem_fun(*this, &ExportToHtmlNoteAddin::export_button_clicked));
+  item->show ();
+  add_plugin_menu_item (item);
+}
+
+
+void ExportToHtmlNoteAddin::export_button_clicked()
+{
+  ExportToHtmlDialog dialog(get_note()->get_title() + ".html");
+  int response = dialog.run();
+  std::string output_path = dialog.get_filename();
+
+  if (response != Gtk::RESPONSE_OK) {
+    return;
+  }
+
+  DBG_OUT("Exporting Note '%s' to '%s'...", get_note()->get_title().c_str(), 
+          output_path.c_str());
+
+  sharp::StreamWriter writer;
+  std::string error_message;
+
+  try {
+    try {
+      // FIXME: Warn about file existing.  Allow overwrite.
+      boost::filesystem::remove(output_path);
+    } 
+    catch(...)
+    {
+      
+    }
+
+    writer.init(output_path);
+    write_html_for_note (writer, get_note(), dialog.get_export_linked(), 
+                         dialog.get_export_linked_all());
+
+    // Save the dialog preferences now that the note has
+    // successfully been exported
+    dialog.save_preferences ();
+
+    try {
+      sharp::Uri output_uri(output_path);
+      gnote::utils::open_url(output_uri.get_absolute_uri());
+    } 
+    catch (const Glib::Exception & ex) {
+      ERR_OUT ("Could not open exported note in a web browser: %s",
+               ex.what().c_str());
+
+      std::string detail = str(boost::format(
+                                 _("Your note was exported to \"%1%\"."))
+                               % output_path);
+
+      // Let the user know the note was saved successfully
+      // even though showing the note in a web browser failed.
+      gnote::utils::HIGMessageDialog msg_dialog(
+        get_window(),
+        GTK_DIALOG_DESTROY_WITH_PARENT,
+        Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
+        _("Note exported successfully"),
+        detail);
+      msg_dialog.run();
+    }
+  } 
+#if 0
+  catch (UnauthorizedAccessException) {
+    error_message = Catalog.GetString ("Access denied.");
+  } 
+  catch (DirectoryNotFoundException) {
+    error_message = Catalog.GetString ("Folder does not exist.");
+  } 
+#endif
+  catch (const sharp::Exception & e) {
+    ERR_OUT("Could not export: %s", e.what());
+
+    error_message = e.what();
+  } 
+  writer.close ();
+
+  if (!error_message.empty())
+  {
+    ERR_OUT("Could not export: %s", error_message.c_str());
+
+    std::string msg = str(boost::format(
+                            _("Could not save the file \"%s\"")) 
+                          % output_path.c_str());
+
+    gnote::utils::HIGMessageDialog msg_dialog(&dialog, 
+                                              GTK_DIALOG_DESTROY_WITH_PARENT,
+                                              Gtk::MESSAGE_ERROR, 
+                                              Gtk::BUTTONS_OK,
+                                              msg, error_message);
+    msg_dialog.run();
+  }
+}
+
+
+
+static void to_lower(xmlXPathParserContextPtr ctxt,
+                     int)
+{
+  const xmlChar *input = xmlXPathPopString(ctxt);
+  gchar * lower = g_utf8_strdown((const gchar*)input, -1);
+  xmlXPathReturnString(ctxt, xmlStrdup((const xmlChar*)lower));
+  g_free(lower);
+}
+
+
+sharp::XslTransform & ExportToHtmlNoteAddin::get_note_xsl()
+{
+  if(s_xsl == NULL) {
+    int result = xsltRegisterExtModuleFunction((const xmlChar *)"ToLower",
+                                               (const xmlChar *)"http://beatniksoftware.com/tomboy";, 
+                                               &to_lower);
+    DBG_OUT("xsltRegisterExtModule %d", result);
+    if(result == -1) {
+      DBG_OUT("xsltRegisterExtModule failed");
+    }
+
+    s_xsl = new sharp::XslTransform;
+    std::string stylesheet_file = DATADIR "/gnote/" STYLESHEET_NAME;
+
+    if (boost::filesystem::exists (stylesheet_file)) {
+      DBG_OUT("ExportToHTML: Using user-custom %s file.", STYLESHEET_NAME);
+      s_xsl->load(stylesheet_file);
+    } 
+#if 0
+    else {
+      Stream resource = asm.GetManifestResourceStream (stylesheet_name);
+      if (resource != null) {
+        XmlTextReader reader = new XmlTextReader (resource);
+        s_xsl->load (reader, null, null);
+        resource.Close ();
+      } 
+      else {
+        DBG_OUT("Unable to find HTML export template '%s'.", STYLESHEET_NAME);
+      }
+    }
+#endif
+
+  }
+  return *s_xsl;
+}
+
+
+
+
+void ExportToHtmlNoteAddin::write_html_for_note (sharp::StreamWriter & writer, 
+                                                 const gnote::Note::Ptr & note, 
+                                                 bool export_linked, 
+                                                 bool export_linked_all)
+{
+  std::string s_writer;
+  s_writer = gnote::NoteArchiver::write_string(note->data());
+  xmlDocPtr doc = xmlParseMemory(s_writer.c_str(), s_writer.size());
+
+  sharp::XsltArgumentList args;
+  args.add_param ("export-linked", "", export_linked);
+  args.add_param ("export-linked-all", "", export_linked_all);
+  args.add_param ("root-note", "", note->get_title());
+
+
+  if (Preferences::obj().get<bool>(Preferences::ENABLE_CUSTOM_FONT)) {
+    std::string font_face 
+      = Preferences::obj().get<std::string>(Preferences::CUSTOM_FONT_FACE);
+    Pango::FontDescription font_desc (font_face);
+    std::string font = str(boost::format("font-family:'%1%';")
+                           % font_desc.get_family());
+
+    args.add_param ("font", "", font);
+  }
+
+  NoteNameResolver resolver(note->manager(), note);
+  get_note_xsl().transform(doc, args, writer, resolver);
+
+  xmlFreeDoc(doc);
+}
+
+
+}
+
diff --git a/src/addins/exporttohtml/exporttohtmlnoteaddin.hpp b/src/addins/exporttohtml/exporttohtmlnoteaddin.hpp
new file mode 100644
index 0000000..c5c69a4
--- /dev/null
+++ b/src/addins/exporttohtml/exporttohtmlnoteaddin.hpp
@@ -0,0 +1,79 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+
+
+
+
+#ifndef _EXPORTTOHTML_ADDIN_HPP_
+#define _EXPORTTOHTML_ADDIN_HPP_
+
+#include <gtkmm/imagemenuitem.h>
+
+#include "sharp/dynamicmodule.hpp"
+#include "sharp/streamwriter.hpp"
+#include "sharp/xsltransform.hpp"
+#include "note.hpp"
+#include "noteaddin.hpp"
+
+namespace exporttohtml {
+
+
+class ExportToHtmlModule
+  : public sharp::DynamicModule
+{
+public:
+  ExportToHtmlModule();
+  virtual const char * id() const;
+  virtual const char * name() const;
+  virtual const char * description() const;
+  virtual const char * authors() const;
+  virtual const char * category() const;
+  virtual const char * version() const;
+};
+
+
+DECLARE_MODULE(ExportToHtmlModule);
+
+class ExportToHtmlNoteAddin
+  : public gnote::NoteAddin
+{
+public:
+  static ExportToHtmlNoteAddin* create()
+    {
+      return new ExportToHtmlNoteAddin;
+    }
+  virtual void initialize();
+  virtual void shutdown();
+  virtual void on_note_opened();
+
+
+private:
+  sharp::XslTransform & get_note_xsl();
+  void export_button_clicked();
+  void write_html_for_note (sharp::StreamWriter &, const gnote::Note::Ptr &, bool, bool);
+
+  Gtk::ImageMenuItem * m_item;
+  static sharp::XslTransform *s_xsl;
+};
+
+}
+
+#endif
diff --git a/src/addins/exporttohtml/notenameresolver.hpp b/src/addins/exporttohtml/notenameresolver.hpp
new file mode 100644
index 0000000..bce6b1e
--- /dev/null
+++ b/src/addins/exporttohtml/notenameresolver.hpp
@@ -0,0 +1,38 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+
+
+#include <note.hpp>
+#include <notemanager.hpp>
+
+namespace exporttohtml {
+
+class NoteNameResolver
+  : public sharp::XmlResolver
+{
+public:
+  NoteNameResolver(const gnote::NoteManager &, const gnote::Note::Ptr &)
+    {}
+};
+
+
+
+}
diff --git a/src/sharp/streamwriter.cpp b/src/sharp/streamwriter.cpp
new file mode 100644
index 0000000..613eda5
--- /dev/null
+++ b/src/sharp/streamwriter.cpp
@@ -0,0 +1,71 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+
+
+#include "sharp/streamwriter.hpp"
+
+#include "debug.hpp"
+
+namespace sharp {
+
+StreamWriter::StreamWriter()
+  : m_file(NULL)
+{
+}
+
+StreamWriter::~StreamWriter()
+{
+  if(m_file) {
+    fclose(m_file);
+  }
+}
+
+void StreamWriter::init(const std::string & filename)
+{
+  m_file = fopen(filename.c_str(), "wb");
+}
+
+
+void StreamWriter::write(const std::string & text)
+{
+  fprintf(m_file, "%s", text.c_str());
+}
+
+  void StreamWriter::write(const xmlBufferPtr buffer)
+{
+  xmlBufferDump(m_file, buffer);
+}
+
+
+void StreamWriter::close()
+{
+  fclose(m_file);
+  m_file = NULL;
+}
+
+
+}
diff --git a/src/sharp/streamwriter.hpp b/src/sharp/streamwriter.hpp
new file mode 100644
index 0000000..facc6d4
--- /dev/null
+++ b/src/sharp/streamwriter.hpp
@@ -0,0 +1,64 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+#ifndef __SHARP_STREAMWRITER_HPP_
+#define __SHARP_STREAMWRITER_HPP_
+
+#include <stdio.h>
+
+#include <string>
+
+#include <libxml/tree.h>
+
+namespace sharp {
+
+
+class StreamWriter
+//  : public TextWriter
+{
+public:
+  StreamWriter();
+  ~StreamWriter();
+
+  void init(const std::string &);
+
+  FILE * file()
+    {
+      return m_file;
+    }
+
+  void write(const std::string & );
+  void write(const xmlBufferPtr);
+
+  void close();
+private:
+  FILE * m_file;
+};
+
+}
+
+
+#endif
diff --git a/src/sharp/uri.cpp b/src/sharp/uri.cpp
index e991184..fa244f4 100644
--- a/src/sharp/uri.cpp
+++ b/src/sharp/uri.cpp
@@ -80,6 +80,12 @@ namespace sharp {
   }
 
 
+  std::string Uri::get_absolute_uri() const
+  {
+    return m_uri;
+  }
+
+
   /** this is a very minimalistic implementation */
   std::string Uri::escape_uri_string(const std::string &s)
   {
diff --git a/src/sharp/uri.hpp b/src/sharp/uri.hpp
index 392222d..8548ca7 100644
--- a/src/sharp/uri.hpp
+++ b/src/sharp/uri.hpp
@@ -47,6 +47,7 @@ namespace sharp {
     bool is_file() const;
     std::string local_path() const;
     std::string get_host() const;
+    std::string get_absolute_uri() const;
     static std::string escape_uri_string(const std::string &);
   private:
     bool _is_scheme(const std::string & scheme) const;
diff --git a/src/sharp/xmlresolver.hpp b/src/sharp/xmlresolver.hpp
new file mode 100644
index 0000000..b097efa
--- /dev/null
+++ b/src/sharp/xmlresolver.hpp
@@ -0,0 +1,43 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+
+
+#ifndef _SHARP_XML_RESOLVER_HPP__
+#define _SHARP_XML_RESOLVER_HPP__
+
+
+namespace sharp {
+
+class XmlResolver
+{
+public:
+};
+
+}
+
+
+#endif
diff --git a/src/sharp/xmlwriter.cpp b/src/sharp/xmlwriter.cpp
index e4b2150..a2b564a 100644
--- a/src/sharp/xmlwriter.cpp
+++ b/src/sharp/xmlwriter.cpp
@@ -42,6 +42,14 @@ namespace sharp {
     m_writer = xmlNewTextWriterFilename(filename.c_str(), 0);
   }
 
+  
+  XmlWriter::XmlWriter(xmlDocPtr doc)
+    : m_buf(NULL)
+  {
+    m_writer = xmlNewTextWriterTree(doc, NULL, 0);
+  }
+
+
   XmlWriter::~XmlWriter()
   {
     xmlFreeTextWriter(m_writer);
diff --git a/src/sharp/xmlwriter.hpp b/src/sharp/xmlwriter.hpp
index a957e64..1e7952c 100644
--- a/src/sharp/xmlwriter.hpp
+++ b/src/sharp/xmlwriter.hpp
@@ -50,7 +50,8 @@ namespace sharp {
   {
   public:
     XmlWriter();
-    XmlWriter(const std::string & filename);    
+    XmlWriter(const std::string & filename);
+    XmlWriter(xmlDocPtr doc);
     ~XmlWriter();
     int write_start_document()
       {
diff --git a/src/sharp/xsltargumentlist.cpp b/src/sharp/xsltargumentlist.cpp
new file mode 100644
index 0000000..0d11db4
--- /dev/null
+++ b/src/sharp/xsltargumentlist.cpp
@@ -0,0 +1,69 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include <stdlib.h>
+
+#include <boost/format.hpp>
+
+#include "sharp/map.hpp"
+#include "sharp/xsltargumentlist.hpp"
+
+namespace sharp {
+
+
+void XsltArgumentList::add_param(const char* name, const char * /*uri*/, const std::string & value)
+{
+  std::string pv = str(boost::format("\"%1%\"") % value);
+  m_args.push_back(std::make_pair(name, pv));
+}
+
+
+void XsltArgumentList::add_param(const char* name, const char * /*uri*/, bool value)
+{
+  m_args.push_back(std::make_pair(name, value?"1":"0"));
+}
+
+
+const char ** XsltArgumentList::get_xlst_params() const
+{
+  const char **params = NULL;
+
+  params = (const char**)calloc(m_args.size() * 2 + 1, sizeof(char*));
+  const_iterator iter(m_args.begin());
+  const_iterator e(m_args.end());
+
+  const char **cur = params;
+  for( ; iter != e; ++iter) {
+    *cur = iter->first.c_str();
+    ++cur;
+    *cur = iter->second.c_str();
+    ++cur;
+  }
+
+  return params;
+}
+
+
+}
diff --git a/src/sharp/xsltargumentlist.hpp b/src/sharp/xsltargumentlist.hpp
new file mode 100644
index 0000000..70dfd58
--- /dev/null
+++ b/src/sharp/xsltargumentlist.hpp
@@ -0,0 +1,70 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+
+#ifndef __SHARP_XSLTARGUMENTLIST_HPP_
+#define __SHARP_XSLTARGUMENTLIST_HPP_
+
+#include <list>
+#include <string>
+#include <utility>
+
+namespace sharp {
+
+/** argument list for %XslTransform */
+class XsltArgumentList
+{
+public:
+  typedef std::list<std::pair<std::string,std::string> > container_t;
+  typedef container_t::const_iterator const_iterator;
+
+  /** add a string parameter */
+  void add_param(const char* name, const char *uri, const std::string &);
+  /** add a bool parameter */
+  void add_param(const char* name, const char *uri, bool);
+
+  /** returns a param array suitable for libxslt. Caller 
+   *  must call free().
+   */
+  const char ** get_xlst_params() const;
+
+  /** */
+  size_t size() const
+    { return m_args.size(); }
+  const_iterator begin() const
+    { return m_args.begin(); }
+  const_iterator end() const
+    { return m_args.end(); }
+private:
+
+  container_t m_args;
+};
+
+
+}
+
+
+#endif
diff --git a/src/sharp/xsltransform.cpp b/src/sharp/xsltransform.cpp
new file mode 100644
index 0000000..adf23d1
--- /dev/null
+++ b/src/sharp/xsltransform.cpp
@@ -0,0 +1,90 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+
+#include <libxslt/xsltutils.h>
+
+#include "sharp/exception.hpp"
+#include "sharp/xmlwriter.hpp"
+#include "sharp/xsltransform.hpp"
+#include "debug.hpp"
+
+namespace sharp {
+
+
+XslTransform:: XslTransform()
+  : m_stylesheet(NULL)
+{
+}
+
+
+XslTransform::~XslTransform()
+{
+  if(m_stylesheet) {
+    xsltFreeStylesheet(m_stylesheet);
+  }
+}
+
+
+void XslTransform::load(const std::string & sheet)
+{
+  if(m_stylesheet) {
+    xsltFreeStylesheet(m_stylesheet);
+  }
+  m_stylesheet = xsltParseStylesheetFile((const xmlChar *)sheet.c_str());
+  DBG_ASSERT(m_stylesheet, "stylesheet failed to load");
+}
+
+
+void XslTransform::transform(xmlDocPtr doc, const XsltArgumentList & args, StreamWriter & output, const XmlResolver & /*resolved*/)
+{
+  const char **params = NULL;
+  if(m_stylesheet == NULL) {
+    ERR_OUT("NULL stylesheet");
+    return;
+  }
+
+  xmlDocPtr res;
+
+  params = args.get_xlst_params();
+
+  res = xsltApplyStylesheet(m_stylesheet, doc, params);
+  free(params);
+  if(res) {
+    xmlOutputBufferPtr output_buf 
+      = xmlOutputBufferCreateFile(output.file(), 
+                                  xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8));
+    xsltSaveResultTo(output_buf, res, m_stylesheet);
+    xmlOutputBufferClose(output_buf);
+  
+    xmlFreeDoc(res);
+  }
+  else {
+    // FIXME get the real error message
+    throw(sharp::Exception("XSLT Error"));
+  }
+}
+
+}
diff --git a/src/sharp/xsltransform.hpp b/src/sharp/xsltransform.hpp
new file mode 100644
index 0000000..dc30746
--- /dev/null
+++ b/src/sharp/xsltransform.hpp
@@ -0,0 +1,63 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+
+#ifndef __SHARP_XSLTRANSFORM_HPP_
+#define __SHARP_XSLTRANSFORM_HPP_
+
+#include <map>
+#include <string>
+
+#include <libxml/tree.h>
+#include <libxslt/transform.h>
+
+#include "sharp/streamwriter.hpp"
+#include "sharp/xmlresolver.hpp"
+#include "sharp/xsltargumentlist.hpp"
+
+
+namespace sharp {
+
+class XslTransform
+{
+public:
+  XslTransform();
+  ~XslTransform();
+
+  /** load the stylesheet */
+  void load(const std::string &);
+  /** run the XLS transformation */
+  void transform(xmlDocPtr, const XsltArgumentList &, StreamWriter &, const XmlResolver &);
+
+private:
+  xsltStylesheetPtr m_stylesheet;
+};
+
+
+}
+
+
+#endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]