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
Stylesheet
fromdocument
.
Instance Method Summary
-
#apply_to(document, params = []) ⇒ String
Apply an
::Nokogiri::XSLT
stylesheet to an::Nokogiri::XML::Document
and serialize it properly. -
#serialize(document)
Serialize
document
to an xml string, as specified by themethod
parameter in theStylesheet
. -
#transform(document)
Transform an
::Nokogiri::XML::Document
as 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
-
document
is an instance of::Nokogiri::XML::Document
to transform -
params
is an array of strings used as::Nokogiri::XSLT
parameters, 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::XSLT
parameters.
- 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) ; }