Class: Nokogiri::XSLT::Stylesheet
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | lib/nokogiri/xslt/stylesheet.rb, ext/nokogiri/xslt_stylesheet.c |
Overview
A Stylesheet represents an ::Nokogiri::XSLT Stylesheet object. Stylesheet creation is done through Nokogiri.XSLT. Here is an example of transforming an ::Nokogiri::XML::Document with a Stylesheet:
doc = Nokogiri::XML(File.read('some_file.xml'))
xslt = Nokogiri::XSLT(File.read('some_transformer.xslt'))
xslt.transform(doc) # => Nokogiri::XML::Document
Many XSLT transformations include serialization behavior to emit a non-XML document. For these cases, please take care to invoke the #serialize method on the result of the transformation:
doc = Nokogiri::XML(File.read('some_file.xml'))
xslt = Nokogiri::XSLT(File.read('some_transformer.xslt'))
xslt.serialize(xslt.transform(doc)) # => String
or use the #apply_to method, which is a shortcut for ‘serialize(transform(document))`:
doc = Nokogiri::XML(File.read('some_file.xml'))
xslt = Nokogiri::XSLT(File.read('some_transformer.xslt'))
xslt.apply_to(doc) # => String
See #transform for more information and examples.
Class Method Summary
-
.parse_stylesheet_doc(document)
Parse an
Stylesheetfromdocument.
Instance Method Summary
-
#apply_to(document, params = []) ⇒ String
Apply an
::Nokogiri::XSLTstylesheet to an::Nokogiri::XML::Documentand serialize it properly. -
#serialize(document)
Serialize
documentto an xml string, as specified by themethodparameter in theStylesheet. -
#transform(document)
Transform an
::Nokogiri::XML::Documentas defined by anStylesheet.
Class Method Details
.parse_stylesheet_doc(document)
Parse an Stylesheet from document.
- Parameters
-
document(Nokogiri::XML::Document) the document to be parsed.
- Returns
-
Stylesheet
# File 'ext/nokogiri/xslt_stylesheet.c', line 81
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);
}
Instance Method Details
#apply_to(document, params = []) ⇒ String
Apply an ::Nokogiri::XSLT stylesheet to an ::Nokogiri::XML::Document and serialize it properly. This method is equivalent to calling #serialize on the result of #transform.
- Parameters
-
documentis an instance of::Nokogiri::XML::Documentto transform -
paramsis an array of strings used as::Nokogiri::XSLTparameters, passed into #transform
- Returns
-
A string containing the serialized result of the transformation.
See #transform for more information and examples.
#serialize(document)
Serialize document to an xml string, as specified by the method parameter in the Stylesheet.
# File 'ext/nokogiri/xslt_stylesheet.c', line 114
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,
&nokogiri_xslt_stylesheet_tuple_type,
wrapper
);
xsltSaveResultToString(&doc_ptr, &doc_len, xml, wrapper->ss);
rval = NOKOGIRI_STR_NEW(doc_ptr, doc_len);
xmlFree(doc_ptr);
return rval ;
}
#transform(document)
#transform(document, params = {})
Transform an ::Nokogiri::XML::Document as defined by an Stylesheet.
- Parameters
-
document(Nokogiri::XML::Document) the document to be transformed. -
params(Hash, Array) strings used as::Nokogiri::XSLTparameters.
- 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 Nokogiri::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 ::Nokogiri::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 Nokogiri::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"
# File 'ext/nokogiri/xslt_stylesheet.c', line 249
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, &nokogiri_xslt_stylesheet_tuple_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) ;
}