|
From: <vac...@us...> - 2009-06-02 16:20:13
|
Revision: 149
http://xmlwrapp.svn.sourceforge.net/xmlwrapp/?rev=149&view=rev
Author: vaclavslavik
Date: 2009-06-02 16:20:11 +0000 (Tue, 02 Jun 2009)
Log Message:
-----------
Fixed xslt::stylesheet::apply() to detect and report errors.
Modified Paths:
--------------
trunk/NEWS
trunk/include/xsltwrapp/stylesheet.h
trunk/src/libxslt/init.cxx
trunk/src/libxslt/stylesheet.cxx
trunk/tests/xslt/test_xslt.cxx
Added Paths:
-----------
trunk/tests/xslt/data/with_errors.xsl
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2009-05-31 18:54:31 UTC (rev 148)
+++ trunk/NEWS 2009-06-02 16:20:11 UTC (rev 149)
@@ -5,6 +5,8 @@
Converted test suite to Boost Test.
+ Fixed xslt::stylesheet::apply() to detect and report errors.
+
Version 0.6.0
Fixed libxmlwrapp to not depend on libxslt if XSLT support
Modified: trunk/include/xsltwrapp/stylesheet.h
===================================================================
--- trunk/include/xsltwrapp/stylesheet.h 2009-05-31 18:54:31 UTC (rev 148)
+++ trunk/include/xsltwrapp/stylesheet.h 2009-06-02 16:20:11 UTC (rev 149)
@@ -58,6 +58,8 @@
class stylesheet
{
public:
+ struct pimpl;
+
/// Type for passing parameters to the stylesheet
typedef std::map<std::string, std::string> param_type;
@@ -160,7 +162,6 @@
const std::string& get_error_message() const;
private:
- struct pimpl;
pimpl *pimpl_;
// an xslt::stylesheet cannot yet be copied or assigned to.
Modified: trunk/src/libxslt/init.cxx
===================================================================
--- trunk/src/libxslt/init.cxx 2009-05-31 18:54:31 UTC (rev 148)
+++ trunk/src/libxslt/init.cxx 2009-06-02 16:20:11 UTC (rev 149)
@@ -49,7 +49,8 @@
extern "C" void xslt_error(void *, const char*, ...)
{
- // don't do anything
+ // don't do anything; we install context-specific error handler to
+ // catch errors while applying a stylesheet
}
} // anonymous namespace
@@ -79,7 +80,8 @@
// set some defautls
process_xincludes(true);
- // keep libxslt silent
+ // keep libxslt silent; we install context-specific error handler to
+ // catch errors while applying a stylesheet
xsltSetGenericErrorFunc(0, xslt_error);
xsltSetGenericDebugFunc(0, xslt_error);
Modified: trunk/src/libxslt/stylesheet.cxx
===================================================================
--- trunk/src/libxslt/stylesheet.cxx 2009-05-31 18:54:31 UTC (rev 148)
+++ trunk/src/libxslt/stylesheet.cxx 2009-06-02 16:20:11 UTC (rev 149)
@@ -57,6 +57,17 @@
#include <vector>
#include <map>
+
+struct xslt::stylesheet::pimpl
+{
+ pimpl (void) : ss_(0), errors_occured_(false) { }
+
+ xsltStylesheetPtr ss_;
+ xml::document doc_;
+ std::string error_;
+ bool errors_occured_;
+};
+
namespace
{
@@ -110,35 +121,76 @@
}
-xmlDocPtr apply_stylesheet(xsltStylesheetPtr s, xmlDocPtr d,
+extern "C" void xsltwrapp_error_cb(void *c, const char *message, ...)
+{
+ xsltTransformContextPtr ctxt = static_cast<xsltTransformContextPtr>(c);
+ xslt::stylesheet::pimpl *impl = static_cast<xslt::stylesheet::pimpl*>(ctxt->_private);
+
+ impl->errors_occured_ = true;
+
+ // tell the processor to stop when it gets a chance:
+ if ( ctxt->state == XSLT_STATE_OK )
+ ctxt->state = XSLT_STATE_STOPPED;
+
+ // concatenate all error messages:
+ if ( impl->errors_occured_ )
+ impl->error_.append("\n");
+
+ std::string formatted;
+
+ va_list ap;
+ va_start(ap, message);
+ xml::impl::printf2string(formatted, message, ap);
+ va_end(ap);
+
+ impl->error_.append(formatted);
+}
+
+
+xmlDocPtr apply_stylesheet(xslt::stylesheet::pimpl *impl,
+ xmlDocPtr doc,
const xslt::stylesheet::param_type *p = NULL)
{
- /*
- * TODO TODO TODO TODO
- *
- * use a transform context to capture error messages
- *
- * TODO TODO TODO TODO
- */
+ xsltStylesheetPtr style = impl->ss_;
+
std::vector<const char*> v;
if (p)
make_vector_param(v, *p);
- return xsltApplyStylesheet(s, d, p ? &v[0] : 0);
-}
-} // end of anonymous namespace
+ xsltTransformContextPtr ctxt = xsltNewTransformContext(style, doc);
+ ctxt->_private = impl;
+ xsltSetTransformErrorFunc(ctxt, ctxt, xsltwrapp_error_cb);
+ // clear the error flag before applying the stylesheet
+ impl->errors_occured_ = false;
-struct xslt::stylesheet::pimpl
-{
- pimpl (void) : ss_(0) { }
+ xmlDocPtr result =
+ xsltApplyStylesheetUser(style, doc, p ? &v[0] : 0, NULL, NULL, ctxt);
- xsltStylesheetPtr ss_;
- xml::document doc_;
- std::string error_;
-};
+ xsltFreeTransformContext(ctxt);
+ // it's possible there was an error that didn't prevent creation of some
+ // (incorrect) document
+ if ( result && impl->errors_occured_ )
+ {
+ xmlFreeDoc(result);
+ return NULL;
+ }
+ if ( !result )
+ {
+ // set generic error message if nothing more specific is known
+ if ( impl->error_.empty() )
+ impl->error_ = "unknown XSLT transformation error";
+ return NULL;
+ }
+
+ return result;
+}
+
+} // end of anonymous namespace
+
+
xslt::stylesheet::stylesheet(const char *filename)
{
std::auto_ptr<pimpl> ap(pimpl_ = new pimpl);
@@ -192,7 +244,7 @@
bool xslt::stylesheet::apply(const xml::document &doc, xml::document &result)
{
xmlDocPtr input = static_cast<xmlDocPtr>(doc.get_doc_data_read_only());
- xmlDocPtr xmldoc = apply_stylesheet(pimpl_->ss_, input);
+ xmlDocPtr xmldoc = apply_stylesheet(pimpl_, input);
if (xmldoc)
{
@@ -208,7 +260,7 @@
const param_type &with_params)
{
xmlDocPtr input = static_cast<xmlDocPtr>(doc.get_doc_data_read_only());
- xmlDocPtr xmldoc = apply_stylesheet(pimpl_->ss_, input, &with_params);
+ xmlDocPtr xmldoc = apply_stylesheet(pimpl_, input, &with_params);
if (xmldoc)
{
@@ -223,14 +275,10 @@
xml::document& xslt::stylesheet::apply(const xml::document &doc)
{
xmlDocPtr input = static_cast<xmlDocPtr>(doc.get_doc_data_read_only());
- xmlDocPtr xmldoc = apply_stylesheet(pimpl_->ss_, input);
+ xmlDocPtr xmldoc = apply_stylesheet(pimpl_, input);
- if (xmldoc == 0)
- {
- if (pimpl_->error_.empty())
- pimpl_->error_ = "unknown XSLT transformation error";
+ if ( !xmldoc )
throw std::runtime_error(pimpl_->error_);
- }
pimpl_->doc_.set_doc_data_from_xslt(xmldoc, new result_impl(xmldoc, pimpl_->ss_));
return pimpl_->doc_;
@@ -241,14 +289,10 @@
const param_type &with_params)
{
xmlDocPtr input = static_cast<xmlDocPtr>(doc.get_doc_data_read_only());
- xmlDocPtr xmldoc = apply_stylesheet(pimpl_->ss_, input, &with_params);
+ xmlDocPtr xmldoc = apply_stylesheet(pimpl_, input, &with_params);
- if (xmldoc == 0)
- {
- if (pimpl_->error_.empty())
- pimpl_->error_ = "unknown XSLT transformation error";
+ if ( !xmldoc )
throw std::runtime_error(pimpl_->error_);
- }
pimpl_->doc_.set_doc_data_from_xslt(xmldoc, new result_impl(xmldoc, pimpl_->ss_));
return pimpl_->doc_;
Added: trunk/tests/xslt/data/with_errors.xsl
===================================================================
--- trunk/tests/xslt/data/with_errors.xsl (rev 0)
+++ trunk/tests/xslt/data/with_errors.xsl 2009-06-02 16:20:11 UTC (rev 149)
@@ -0,0 +1,19 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:output method="xml"/>
+
+ <xsl:template name="foo">
+ <output>
+ <xsl:value-of select="$x"/>
+ </output>
+ <!-- this is intentionally invalid: the parameters must be declared
+ at the top of the template -->
+ <xsl:param name="x"/>
+ </xsl:template>
+
+ <xsl:template match="/">
+ <xsl:call-template name="foo">
+ <xsl:with-param name="x">42</xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+</xsl:stylesheet>
Modified: trunk/tests/xslt/test_xslt.cxx
===================================================================
--- trunk/tests/xslt/test_xslt.cxx 2009-05-31 18:54:31 UTC (rev 148)
+++ trunk/tests/xslt/test_xslt.cxx 2009-06-02 16:20:11 UTC (rev 149)
@@ -131,4 +131,30 @@
}
+/*
+ * Tests libxslt errors reporting
+ */
+
+BOOST_AUTO_TEST_CASE( xsl_with_errors )
+{
+ xslt::stylesheet style(test_file_path("xslt/data/with_errors.xsl").c_str());
+ xml::tree_parser parser(test_file_path("xslt/data/input.xml").c_str());
+
+ xml::document result;
+ BOOST_CHECK( !style.apply(parser.get_document(), result) );
+}
+
+BOOST_AUTO_TEST_CASE( xsl_with_errors_throw )
+{
+ xslt::stylesheet style(test_file_path("xslt/data/with_errors.xsl").c_str());
+ xml::tree_parser parser(test_file_path("xslt/data/input.xml").c_str());
+
+ BOOST_CHECK_THROW
+ (
+ style.apply(parser.get_document()),
+ std::exception
+ );
+}
+
+
BOOST_AUTO_TEST_SUITE_END()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|