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)


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'ext/libxslt/ruby_xslt_stylesheet.c', line 42

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

  if (!rb_obj_is_kind_of(document, cXMLDocument))
    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



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

def self.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



20
21
22
23
# File 'lib/libxslt/stylesheet.rb', line 20

def self.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 self.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)


113
114
115
116
117
118
119
120
121
122
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
# File 'ext/libxslt/ruby_xslt_stylesheet.c', line 113

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, cXMLDocument))
    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);
}

#output(doc) ⇒ String

Output 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)


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

VALUE
ruby_xslt_stylesheet_output(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, cXMLDocument))
    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;
}

#transform(doc) ⇒ Object

transform a xml to a string



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

def transform(doc)
  return output(apply(doc))
end