class Nokogiri::XSLT::Stylesheet
A Stylesheet represents an XSLT Stylesheet object. Stylesheet creation is done through Nokogiri.XSLT. Here is an example of transforming an XML::Document with a Stylesheet:
doc = Nokogiri::XML(File.read('some_file.xml')) xslt = Nokogiri::XSLT(File.read('some_transformer.xslt')) puts xslt.transform(doc)
See Nokogiri::XSLT::Stylesheet#transform for more transformation information.
Public Class Methods
Parse a stylesheet from document.
static VALUE
parse_stylesheet_doc(VALUE klass, VALUE xmldocobj)
{
xmlDocPtr xml, xml_cpy;
VALUE errstr, exception;
xsltStylesheetPtr ss ;
xml = noko_xml_document_unwrap(xmldocobj);
errstr = rb_str_new(0, 0);
xsltSetGenericErrorFunc((void *)errstr, xslt_generic_error_handler);
xml_cpy = xmlCopyDoc(xml, 1); /* 1 => recursive */
ss = xsltParseStylesheetDoc(xml_cpy);
xsltSetGenericErrorFunc(NULL, NULL);
if (!ss) {
xmlFreeDoc(xml_cpy);
exception = rb_exc_new3(rb_eRuntimeError, errstr);
rb_exc_raise(exception);
}
return Nokogiri_wrap_xslt_stylesheet(ss);
}
Public Instance Methods
Apply an XSLT stylesheet to an XML::Document. params is an array of strings used as XSLT parameters. returns serialized document
# File lib/nokogiri/xslt/stylesheet.rb, line 22 def apply_to(document, params = []) serialize(transform(document, params)) end
Serialize document to an xml string.
static VALUE
rb_xslt_stylesheet_serialize(VALUE self, VALUE xmlobj)
{
xmlDocPtr xml ;
nokogiriXsltStylesheetTuple *wrapper;
xmlChar *doc_ptr ;
int doc_len ;
VALUE rval ;
xml = noko_xml_document_unwrap(xmlobj);
TypedData_Get_Struct(
self,
nokogiriXsltStylesheetTuple,
&xslt_stylesheet_type,
wrapper
);
xsltSaveResultToString(&doc_ptr, &doc_len, xml, wrapper->ss);
rval = NOKOGIRI_STR_NEW(doc_ptr, doc_len);
xmlFree(doc_ptr);
return rval ;
}
Apply an XSLT stylesheet to an XML::Document.
- Parameters
-
document(Nokogiri::XML::Document) the document to be transformed. -
params(Hash, Array) strings used asXSLTparameters.
- Returns
Example of basic transformation:
xslt = <<~XSLT <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:param name="title"/> <xsl:template match="/"> <html> <body> <h1><xsl:value-of select="$title"/></h1> <ol> <xsl:for-each select="staff/employee"> <li><xsl:value-of select="employeeId"></li> </xsl:for-each> </ol> </body> </html> </xsl:stylesheet> XSLT xml = <<~XML <?xml version="1.0"?> <staff> <employee> <employeeId>EMP0001</employeeId> <position>Accountant</position> </employee> <employee> <employeeId>EMP0002</employeeId> <position>Developer</position> </employee> </staff> XML doc = Nokogiri::XML::Document.parse(xml) stylesheet = Nokogiri::XSLT.parse(xslt)
⚠ Note that the h1 element is empty because no param has been provided!
stylesheet.transform(doc).to_xml # => "<html><body>\n" + # "<h1></h1>\n" + # "<ol>\n" + # "<li>EMP0001</li>\n" + # "<li>EMP0002</li>\n" + # "</ol>\n" + # "</body></html>\n"
Example of using an input parameter hash:
⚠ The title is populated, but note how we need to quote-escape the value.
stylesheet.transform(doc, { "title" => "'Employee List'" }).to_xml # => "<html><body>\n" + # "<h1>Employee List</h1>\n" + # "<ol>\n" + # "<li>EMP0001</li>\n" + # "<li>EMP0002</li>\n" + # "</ol>\n" + # "</body></html>\n"
Example using the XSLT.quote_params helper method to safely quote-escape strings:
stylesheet.transform(doc, Nokogiri::XSLT.quote_params({ "title" => "Aaron's List" })).to_xml # => "<html><body>\n" + # "<h1>Aaron's List</h1>\n" + # "<ol>\n" + # "<li>EMP0001</li>\n" + # "<li>EMP0002</li>\n" + # "</ol>\n" + # "</body></html>\n"
Example using an array of XSLT parameters
You can also use an array if you want to.
stylesheet.transform(doc, ["title", "'Employee List'"]).to_xml # => "<html><body>\n" + # "<h1>Employee List</h1>\n" + # "<ol>\n" + # "<li>EMP0001</li>\n" + # "<li>EMP0002</li>\n" + # "</ol>\n" + # "</body></html>\n"
Or pass an array to XSLT.quote_params:
stylesheet.transform(doc, Nokogiri::XSLT.quote_params(["title", "Aaron's List"])).to_xml # => "<html><body>\n" + # "<h1>Aaron's List</h1>\n" + # "<ol>\n" + # "<li>EMP0001</li>\n" + # "<li>EMP0002</li>\n" + # "</ol>\n" + # "</body></html>\n"
See: Nokogiri::XSLT.quote_params
static VALUE
rb_xslt_stylesheet_transform(int argc, VALUE *argv, VALUE self)
{
VALUE rb_document, rb_param, rb_error_str;
xmlDocPtr c_document ;
xmlDocPtr c_result_document ;
nokogiriXsltStylesheetTuple *wrapper;
const char **params ;
long param_len, j ;
int parse_error_occurred ;
int defensive_copy_p = 0;
rb_scan_args(argc, argv, "11", &rb_document, &rb_param);
if (NIL_P(rb_param)) { rb_param = rb_ary_new2(0L) ; }
if (!rb_obj_is_kind_of(rb_document, cNokogiriXmlDocument)) {
rb_raise(rb_eArgError, "argument must be a Nokogiri::XML::Document");
}
/* handle hashes as arguments. */
if (T_HASH == TYPE(rb_param)) {
rb_param = rb_funcall(rb_param, rb_intern("to_a"), 0);
rb_param = rb_funcall(rb_param, rb_intern("flatten"), 0);
}
Check_Type(rb_param, T_ARRAY);
c_document = noko_xml_document_unwrap(rb_document);
TypedData_Get_Struct(self, nokogiriXsltStylesheetTuple, &xslt_stylesheet_type, wrapper);
param_len = RARRAY_LEN(rb_param);
params = ruby_xcalloc((size_t)param_len + 1, sizeof(char *));
for (j = 0 ; j < param_len ; j++) {
VALUE entry = rb_ary_entry(rb_param, j);
const char *ptr = StringValueCStr(entry);
params[j] = ptr;
}
params[param_len] = 0 ;
xsltTransformContextPtr c_transform_context = xsltNewTransformContext(wrapper->ss, c_document);
if (xsltNeedElemSpaceHandling(c_transform_context) &&
noko_xml_document_has_wrapped_blank_nodes_p(c_document)) {
// see https://github.com/sparklemotion/nokogiri/issues/2800
c_document = xmlCopyDoc(c_document, 1);
defensive_copy_p = 1;
}
xsltFreeTransformContext(c_transform_context);
rb_error_str = rb_str_new(0, 0);
xsltSetGenericErrorFunc((void *)rb_error_str, xslt_generic_error_handler);
xmlSetGenericErrorFunc((void *)rb_error_str, xslt_generic_error_handler);
c_result_document = xsltApplyStylesheet(wrapper->ss, c_document, params);
ruby_xfree(params);
if (defensive_copy_p) {
xmlFreeDoc(c_document);
c_document = NULL;
}
xsltSetGenericErrorFunc(NULL, NULL);
xmlSetGenericErrorFunc(NULL, NULL);
parse_error_occurred = (Qfalse == rb_funcall(rb_error_str, rb_intern("empty?"), 0));
if (parse_error_occurred) {
rb_exc_raise(rb_exc_new3(rb_eRuntimeError, rb_error_str));
}
return noko_xml_document_wrap((VALUE)0, c_result_document) ;
}