Class: LibXSLT::XSLT::Stylesheet

Inherits:
Object
  • Object
show all
Defined in:
ext/libxslt/ruby_xslt_stylesheet.c,
lib/libxslt/stylesheet.rb,
ext/libxslt/ruby_xslt_stylesheet.c

Overview

The XSLT::Stylesheet represents a XSL stylesheet that can be used to transform an XML document. For usage information refer to XSLT::Stylesheet#apply

Constant Summary collapse

PARSE_OPTIONS =

options to be used for parsing stylesheets

LibXML::XML::Parser::Options::NOCDATA | LibXML::XML::Parser::Options::NOENT

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#XSLT::Stylesheet.new(document) ⇒ XSLT::Stylesheet

Creates a new XSLT stylesheet based on the specified document. For memory management reasons, a copy of the specified document will be made, so its best to create a single copy of a stylesheet and use it multiple times.

stylesheet_doc = XML::Document.file('stylesheet_file')
stylesheet = XSLT::Stylesheet.new(stylesheet_doc)


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'ext/libxslt/ruby_xslt_stylesheet.c', line 51

static VALUE
ruby_xslt_stylesheet_initialize(VALUE self, VALUE document) {
  xmlDocPtr xdoc;
  xmlDocPtr xcopy;
  xsltStylesheetPtr xstylesheet;

  if (!rb_obj_is_kind_of(document, ruby_xslt_stylesheet_document_klass()))
    rb_raise(rb_eTypeError, "Must pass in an XML::Document instance.");
    
  /* NOTE!! Since the stylesheet own the specified document, the easiest 
  *  thing to do from a memory standpoint is too copy it and not expose
  *  the copy to Ruby.  The other solution is expose a memory management
  *  API on the document object for taking ownership of the document
  *  and specifying when it has been freed.  Then the document class
  *  has to be updated to always check and see if the document is 
  *  still valid.  That's all doable, but seems like a pain, so 
  *  just copy the document for now. */
  Data_Get_Struct(document, xmlDoc, xdoc);
  xcopy = xmlCopyDoc(xdoc, 1);
  xstylesheet = xsltParseStylesheetDoc(xcopy);
  xstylesheet->_private = (void *)self;
  DATA_PTR(self) = xstylesheet;
  
  /* Save a reference to the document as an attribute accessable to ruby*/
  return self;
}

Class Method Details

.file(filename) ⇒ Object

create a xslt stylesheet from a file specified by its filename



13
14
15
16
# File 'lib/libxslt/stylesheet.rb', line 13

def file(filename)
  doc = LibXML::XML::Parser.file(filename, :options => PARSE_OPTIONS).parse
  return new(doc)
end

.io(io_object) ⇒ Object

create a xslt stylesheet from an io object



18
19
20
21
# File 'lib/libxslt/stylesheet.rb', line 18

def io(io_object)
  doc = LibXML::XML::Parser.io(io_object, :options => PARSE_OPTIONS).parse
  return new(doc)
end

.string(xml) ⇒ Object

create a xslt stylesheet from a string



8
9
10
11
# File 'lib/libxslt/stylesheet.rb', line 8

def string(xml)
  doc = LibXML::XML::Parser.string(xml, :options => PARSE_OPTIONS).parse
  return new(doc)
end

Instance Method Details

#apply(document, {params}) ⇒ XML::Document

Apply this stylesheet transformation to the provided document. This method may be invoked multiple times.

Params:

  • document - An instance of an XML::Document

  • params - An optional hash table that specifies the values for xsl:param values embedded in the stylesheet.

Example:

stylesheet_doc = XML::Document.file('stylesheet_file')
stylesheet = XSLT::Stylesheet.new(stylesheet_doc)

xml_doc = XML::Document.file('xml_file')
result = stylesheet.apply(xml_doc)
result = stylesheet.apply(xml_doc, {:foo => 'bar'})

Returns:

  • (XML::Document)


123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'ext/libxslt/ruby_xslt_stylesheet.c', line 123

static VALUE
ruby_xslt_stylesheet_apply(int argc, VALUE *argv, VALUE self) {
  xmlDocPtr xdoc;
  xsltStylesheetPtr xstylesheet;
  xmlDocPtr result;
  VALUE document;
  VALUE params;
  int i;
  
  char** pParams;

  if (argc > 2 || argc < 1)
    rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
    
  document = argv[0];
  
  if (!rb_obj_is_kind_of(document, ruby_xslt_stylesheet_document_klass()))
    rb_raise(rb_eTypeError, "Must pass in an XML::Document instance.");

  /* Make sure params is a flat array */
  params = (argc == 2 ? argv[1]: Qnil);
  params = rb_Array(params);
  rb_funcall(params, rb_intern("flatten!"), 0);
  pParams = ruby_xslt_coerce_params(params);
  
  Data_Get_Struct(document, xmlDoc, xdoc);
  Data_Get_Struct(self, xsltStylesheet, xstylesheet);
  
  result = xsltApplyStylesheet(xstylesheet, xdoc, (const char**)pParams);
  
  if (!result)
    rb_raise(eXSLTError, "Transformation failed");
  
  /* Free allocated array of *chars.  Note we don't have to
     free the last array item since its set to NULL. */
  for (i=0; i<(RARRAY_LEN(params)); i++) {
    ruby_xfree(pParams[i]);
  }
  ruby_xfree(pParams);
    
  return rxml_document_wrap(result);
}

#dump_result(doc) ⇒ String

Dump an xml document, usually the result of an xslt transformation, and return the result as a string. Output will be done according to the output specification in the xslt stylesheet. Note that this includes the encoding of the string.

Returns:

  • (String)


330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'ext/libxslt/ruby_xslt_stylesheet.c', line 330

VALUE
ruby_xslt_stylesheet_dump_result(VALUE self, VALUE document) {
// FIXME: set string encoding in ruby 1.9?
  xmlDocPtr xdoc;
  xsltStylesheetPtr xstylesheet;
  xmlChar *result = NULL;
  int len = 0, bytes = 0;
  VALUE rresult;
  
  if (!rb_obj_is_kind_of(document, ruby_xslt_stylesheet_document_klass()))
    rb_raise(rb_eTypeError, "Must pass in an XML::Document instance.");

  Data_Get_Struct(document, xmlDoc, xdoc);
  Data_Get_Struct(self, xsltStylesheet, xstylesheet);
  
  bytes = xsltSaveResultToString(&result, &len,
				 xdoc, xstylesheet);
  if ( bytes == -1 ) {
    rb_raise(rb_eRuntimeError, "error dumping document");
  }

  rresult=rb_str_new((const char*)result,len);
  xmlFree(result);
  return rresult;
}

#save_result(doc, to = $stdout) ⇒ Object

Output an xml document, usually the result of an xslt transformation, to the specified output stream (an IO instance, defaults to $stdout). Output will be done according to the output specification in the xslt stylesheet.

Returns the number of bytes written.



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
319
320
# File 'ext/libxslt/ruby_xslt_stylesheet.c', line 276

VALUE
ruby_xslt_stylesheet_save_result(int argc, VALUE *argv, VALUE self) {
  xmlDocPtr xdoc;
  xsltStylesheetPtr xstylesheet;
  VALUE document;
  OpenFile *fptr;
  VALUE io;
  FILE *out;
  int bytes;
  
  if (argc > 2 || argc < 1)
    rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
    
  document = argv[0];
  
  if (!rb_obj_is_kind_of(document, ruby_xslt_stylesheet_document_klass()))
    rb_raise(rb_eTypeError, "Must pass in an XML::Document instance.");

  switch (argc) {
  case 1:
    io = rb_stdout;
    break;
  case 2:
    io = argv[1];
    if (rb_obj_is_kind_of(io, rb_cIO) == Qfalse)
      rb_raise(rb_eTypeError, "need an IO object");
    break;
  default:
    rb_raise(rb_eArgError, "wrong number of arguments (1 or 2)");
  }

  GetOpenFile(io, fptr);
  rb_io_check_writable(fptr);
  out = GetWriteFile(fptr);

  Data_Get_Struct(document, xmlDoc, xdoc);
  Data_Get_Struct(self, xsltStylesheet, xstylesheet);
  
  bytes = xsltSaveResultToFile(out, xdoc, xstylesheet);
  if ( bytes == -1 ) {
    rb_raise(rb_eRuntimeError, "error saving document");
  }

  return(INT2NUM(bytes));
}

#transform_to_file(doc, io = STDOUT) ⇒ Object

transform a xml to a file (specified by an output stream)



29
30
31
32
# File 'lib/libxslt/stylesheet.rb', line 29

def transform_to_file(doc, io = STDOUT)
  rdoc = apply(doc)
  return save_result(rdoc, io)
end

#transform_to_string(doc) ⇒ Object

transform a xml to a string



24
25
26
27
# File 'lib/libxslt/stylesheet.rb', line 24

def transform_to_string(doc)
  rdoc = apply(doc)
  return dump_result(rdoc)
end