Class: Nokogiri::XSLT::Stylesheet

Inherits:
Object
  • Object
show all
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'))

puts xslt.transform(doc)

See Nokogiri::XSLT::Stylesheet#transform for more transformation information.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.parse_stylesheet_doc(document) ⇒ Object

Parse a stylesheet from document.


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'ext/nokogiri/xslt_stylesheet.c', line 58

static VALUE
parse_stylesheet_doc(VALUE klass, VALUE xmldocobj)
{
  xmlDocPtr xml, xml_cpy;
  VALUE errstr, exception;
  xsltStylesheetPtr ss ;
  Data_Get_Struct(xmldocobj, xmlDoc, xml);

  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

Apply an XSLT stylesheet to an XML::Document. params is an array of strings used as XSLT parameters. returns serialized document


22
23
24
# File 'lib/nokogiri/xslt/stylesheet.rb', line 22

def apply_to(document, params = [])
  serialize(transform(document, params))
end

#serialize(document) ⇒ Object

Serialize document to an xml string.


90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'ext/nokogiri/xslt_stylesheet.c', line 90

static VALUE
serialize(VALUE self, VALUE xmlobj)
{
  xmlDocPtr xml ;
  nokogiriXsltStylesheetTuple *wrapper;
  xmlChar *doc_ptr ;
  int doc_len ;
  VALUE rval ;

  Data_Get_Struct(xmlobj, xmlDoc, xml);
  Data_Get_Struct(self, nokogiriXsltStylesheetTuple, 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

Apply an XSLT stylesheet to an XML::Document.

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


220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
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
# File 'ext/nokogiri/xslt_stylesheet.c', line 220

static VALUE
transform(int argc, VALUE *argv, VALUE self)
{
  VALUE xmldoc, paramobj, errstr, exception ;
  xmlDocPtr xml ;
  xmlDocPtr result ;
  nokogiriXsltStylesheetTuple *wrapper;
  const char **params ;
  long param_len, j ;
  int parse_error_occurred ;

  rb_scan_args(argc, argv, "11", &xmldoc, &paramobj);
  if (NIL_P(paramobj)) { paramobj = rb_ary_new2(0L) ; }
  if (!rb_obj_is_kind_of(xmldoc, cNokogiriXmlDocument)) {
    rb_raise(rb_eArgError, "argument must be a Nokogiri::XML::Document");
  }

  /* handle hashes as arguments. */
  if (T_HASH == TYPE(paramobj)) {
    paramobj = rb_funcall(paramobj, rb_intern("to_a"), 0);
    paramobj = rb_funcall(paramobj, rb_intern("flatten"), 0);
  }

  Check_Type(paramobj, T_ARRAY);

  Data_Get_Struct(xmldoc, xmlDoc, xml);
  Data_Get_Struct(self, nokogiriXsltStylesheetTuple, wrapper);

  param_len = RARRAY_LEN(paramobj);
  params = ruby_xcalloc((size_t)param_len + 1, sizeof(char *));
  for (j = 0 ; j < param_len ; j++) {
    VALUE entry = rb_ary_entry(paramobj, j);
    const char *ptr = StringValueCStr(entry);
    params[j] = ptr;
  }
  params[param_len] = 0 ;

  errstr = rb_str_new(0, 0);
  xsltSetGenericErrorFunc((void *)errstr, xslt_generic_error_handler);
  xmlSetGenericErrorFunc((void *)errstr, xslt_generic_error_handler);

  result = xsltApplyStylesheet(wrapper->ss, xml, params);
  ruby_xfree(params);

  xsltSetGenericErrorFunc(NULL, NULL);
  xmlSetGenericErrorFunc(NULL, NULL);

  parse_error_occurred = (Qfalse == rb_funcall(errstr, rb_intern("empty?"), 0));

  if (parse_error_occurred) {
    exception = rb_exc_new3(rb_eRuntimeError, errstr);
    rb_exc_raise(exception);
  }

  return noko_xml_document_wrap((VALUE)0, result) ;
}