Skip to content

Instantly share code, notes, and snippets.

@sshao
Created October 7, 2014 19:49
Show Gist options
  • Select an option

  • Save sshao/8911889131aad079d283 to your computer and use it in GitHub Desktop.

Select an option

Save sshao/8911889131aad079d283 to your computer and use it in GitHub Desktop.
/* call-seq:
* stylesheet.apply(document, {params}) -> XML::Document
*
* Apply this stylesheet transformation to the provided document.
* This method may be invoked multiple times.
*
* Params:
* * document - An instance of an XML::Document
* * params - An optional hash table that specifies the values for xsl:param values embedded in the stylesheet.
*
* Example:
*
* stylesheet_doc = XML::Document.file('stylesheet_file')
* stylesheet = XSLT::Stylesheet.new(stylesheet_doc)
*
* xml_doc = XML::Document.file('xml_file')
* result = stylesheet.apply(xml_doc)
* result = stylesheet.apply(xml_doc, {:foo => 'bar'})
*/
static VALUE
ruby_xslt_stylesheet_apply(int argc, VALUE *argv, VALUE self) {
if (argc > 2 || argc < 1)
rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
document = argv[0];
if (!rb_obj_is_kind_of(document, cXMLDocument))
rb_raise(rb_eTypeError, "Must pass in an XML::Document instance.");
/* Make sure params is a flat array */
params = (argc == 2 ? argv[1]: Qnil);
params = rb_Array(params);
rb_funcall(params, rb_intern("flatten!"), 0);
pParams = ruby_xslt_coerce_params(params);
Data_Get_Struct(document, xmlDoc, xdoc);
Data_Get_Struct(self, xsltStylesheet, xstylesheet);
result = xsltApplyStylesheet(xstylesheet, xdoc, (const char**)pParams);
if (!result)
rb_raise(eXSLTError, "Transformation failed");
/* Free allocated array of *chars. Note we don't have to
free the last array item since its set to NULL. */
for (i=0; i<RARRAY_LEN(params); i++) {
ruby_xfree(pParams[i]);
}
ruby_xfree(pParams);
return rxml_document_wrap(result);
}
/* call-seq:
* sheet.debug(to = $stdout) => (true|false)
*
* Output a debug dump of this stylesheet to the specified output
* stream (an instance of IO, defaults to $stdout). Requires
* libxml/libxslt be compiled with debugging enabled. If this
* is not the case, a warning is triggered and the method returns
* false.
*/
/*VALUE
ruby_xslt_stylesheet_debug(int argc, VALUE *argv, VALUE self) {
#ifdef LIBXML_DEBUG_ENABLED
OpenFile *fptr;
VALUE io;
FILE *out;
rxml_document_t *parsed;
ruby_xslt_stylesheet *xss;
Data_Get_Struct(self, ruby_xslt_stylesheet, xss);
if (NIL_P(xss->parsed))
rb_raise(eXMLXSLTStylesheetRequireParsedDoc, "must have a parsed XML result");
switch (argc) {
case 0:
io = rb_stdout;
break;
case 1:
io = argv[0];
if (rb_obj_is_kind_of(io, rb_cIO) == Qfalse)
rb_raise(rb_eTypeError, "need an IO object");
break;
default:
rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
}
Data_Get_Struct(xss->parsed, rxml_document_t, parsed);
if (parsed->doc == NULL)
return(Qnil);
GetOpenFile(io, fptr);
rb_io_check_writable(fptr);
out = GetWriteFile(fptr);
xmlDebugDumpDocument(out, parsed->doc);
return(Qtrue);
#else
rb_warn("libxml/libxslt was compiled without debugging support. Please recompile libxml/libxslt and their Ruby modules");
return(Qfalse);
#endif
}
*/
/* TODO should this automatically apply the sheet if not already,
given that we're unlikely to do much else with it? */
/* call-seq:
* sheet.print(to = $stdout) => number_of_bytes
*
* Output the result of the transform to the specified output
* stream (an IO instance, defaults to $stdout). You *must* call
* +apply+ before this method or an exception will be raised.
*/
/*VALUE
ruby_xslt_stylesheet_print(int argc, VALUE *argv, VALUE self) {
OpenFile *fptr;
VALUE io;
FILE *out;
rxml_document_t *parsed;
ruby_xslt_stylesheet *xss;
int bytes;
Data_Get_Struct(self, ruby_xslt_stylesheet, xss);
if (NIL_P(xss->parsed))
rb_raise(eXMLXSLTStylesheetRequireParsedDoc, "must have a parsed XML result");
switch (argc) {
case 0:
io = rb_stdout;
break;
case 1:
io = argv[0];
if (rb_obj_is_kind_of(io, rb_cIO) == Qfalse)
rb_raise(rb_eTypeError, "need an IO object");
break;
default:
rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
}
Data_Get_Struct(xss->parsed, rxml_document_t, parsed);
if (parsed->doc == NULL)
return(Qnil);
GetOpenFile(io, fptr);
rb_io_check_writable(fptr);
out = GetWriteFile(fptr);
bytes = xsltSaveResultToFile(out, parsed->doc, xss->xsp);
return(INT2NUM(bytes));
}*/
/* call-seq:
* stylesheet.output(doc) => string
*
* Output an xml document, usually the result of an xslt
* transformation, and return the result as a string. Output will be
* done according to the output specification in the xslt
* stylesheet. Note that this includes the encoding of the string.
*/
VALUE
ruby_xslt_stylesheet_output(VALUE self, VALUE document) {
// FIXME: set string encoding in ruby 1.9?
xmlDocPtr xdoc;
xsltStylesheetPtr xstylesheet;
xmlChar *result = NULL;
int len = 0, bytes = 0;
VALUE rresult;
if (!rb_obj_is_kind_of(document, cXMLDocument))
rb_raise(rb_eTypeError, "Must pass in an XML::Document instance.");
Data_Get_Struct(document, xmlDoc, xdoc);
Data_Get_Struct(self, xsltStylesheet, xstylesheet);
bytes = xsltSaveResultToString(&result, &len,
xdoc, xstylesheet);
if ( bytes == -1 ) {
rb_raise(rb_eRuntimeError, "error dumping document");
}
rresult=rb_str_new((const char*)result,len);
xmlFree(result);
return rresult;
}
#ifdef RDOC_NEVER_DEFINED
cLibXSLT = rb_define_module("LibXSLT");
cXSLT = rb_define_module_under(cLibXSLT, "XSLT");
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment