Class: Nokogiri::XSLT::Stylesheet
- Inherits:
-
Object
- Object
- Nokogiri::XSLT::Stylesheet
- Defined in:
- lib/nokogiri/xslt/stylesheet.rb,
ext/nokogiri/xslt_stylesheet.c
Overview
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'))
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 Nokogiri::XSLT::Stylesheet#transform for more information and examples.
Class Method Summary collapse
-
.parse_stylesheet_doc(document) ⇒ Object
Parse an XSLT::Stylesheet from
document
.
Instance Method Summary collapse
-
#apply_to(document, params = []) ⇒ Object
:call-seq: apply_to(document, params = []) -> String.
-
#serialize(document) ⇒ Object
Serialize
document
to an xml string, as specified by themethod
parameter in the Stylesheet. -
#transform(*args) ⇒ Object
Transform an XML::Document as defined by an XSLT::Stylesheet.
Class Method Details
.parse_stylesheet_doc(document) ⇒ Object
Parse an XSLT::Stylesheet from document
.
- Parameters
-
document
(Nokogiri::XML::Document) the document to be parsed.
- Returns
-
Nokogiri::XSLT::Stylesheet
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# 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 = []) ⇒ Object
:call-seq:
apply_to(document, params = []) -> String
Apply an XSLT stylesheet to an XML::Document and serialize it properly. This method is equivalent to calling #serialize on the result of #transform.
- Parameters
-
document
is an instance of XML::Document to transform -
params
is an array of strings used as XSLT parameters, passed into #transform
- Returns
-
A string containing the serialized result of the transformation.
See Nokogiri::XSLT::Stylesheet#transform for more information and examples.
44 45 46 |
# File 'lib/nokogiri/xslt/stylesheet.rb', line 44 def apply_to(document, params = []) serialize(transform(document, params)) end |
#serialize(document) ⇒ Object
Serialize document
to an xml string, as specified by the method
parameter in the Stylesheet.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# 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,
&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 ;
}
|
#transform(document) ⇒ Object #transform(document, params = {}) ⇒ Object
Transform an XML::Document as defined by an XSLT::Stylesheet.
- Parameters
-
document
(Nokogiri::XML::Document) the document to be transformed. -
params
(Hash, Array) strings used as XSLT parameters.
- Returns
-
Nokogiri::XML::Document
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
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
# 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, &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) ;
}
|