libxslt-ruby 1.0.1 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,33 @@
1
+ == 1.0.3 / 2011-07-31
2
+
3
+ * Added support for extension function registration. This was adapted from
4
+ Gregoire Lejeune's ruby-xslt library at https://github.com/glejeune/ruby-xslt (Jens Willie).
5
+
6
+ * Update to work with libxml-ruby 2.1.0 and higher (Jens Willie).
7
+
8
+ * Use ENV for rake compiler task configuration (Jens Willie)
9
+
10
+ * Build fixes (Charlie Savage).
11
+
12
+ * Switch to using def files to control library exports (Charlie Savage).
13
+
14
+
15
+ == 1.0.1 / 2011-04-18 Charlie Savage
16
+
17
+ * Modernize gem - add gemspec file, use rake-compiler
18
+
19
+ * Fix Ruby 1.9.2 compile errors
20
+
21
+ * Build fixes
22
+
23
+ * Update tests scripts to make testing during development easier
24
+
25
+
26
+ == 0.9.8 / 2011-01-18 Charlie Savage
27
+
28
+ * Update build environment
29
+
30
+
1
31
  == 0.9.1 / 2008-11-24 Charlie Savage
2
32
 
3
33
  * Support libxml-ruby bindings 0.9.3 and above which has a changed
@@ -13,11 +43,11 @@
13
43
 
14
44
  == 0.8.2 / 2008-07-21 Charlie Savage
15
45
 
16
- * To use LibXSLT you can either require 'xslt' or require 'libxslt'.
17
- The differences is that require 'xslt' mixes the LibXML and
18
- LIBXSLT modules into the global namespace, thereby allowing
46
+ * To use LibXSLT you can either require 'xslt' or require 'libxslt'.
47
+ The differences is that require 'xslt' mixes the LibXML and
48
+ LIBXSLT modules into the global namespace, thereby allowing
19
49
  you to write code such as:
20
- stylesheet = XSLT::Stylesheet.new(XML::Document.new). Note that
50
+ stylesheet = XSLT::Stylesheet.new(XML::Document.new). Note that
21
51
  this is different from 0.8.0 release and may require updating your code.
22
52
 
23
53
  * Support for libxml-ruby 0.8.2
@@ -41,7 +71,7 @@
41
71
 
42
72
  * Simpler api
43
73
 
44
- * Compatibility layer for pre-0.7.0 versions
74
+ * Compatibility layer for pre-0.7.0 versions
45
75
 
46
76
  * Major rewrite, resulting in significantly less code
47
77
 
@@ -54,7 +84,7 @@
54
84
 
55
85
  * Windows support (both lots of memory fixes and binaries)
56
86
 
57
- * New libxslt.rb ruby wrapper, so programs can simply say require 'xslt'
87
+ * New libxslt.rb ruby wrapper, so programs can simply say require 'xslt'
58
88
 
59
89
 
60
90
  == 0.5.0 / 2006-02-27 Ross Bamford <rosco at roscopeco.co.uk>
@@ -76,6 +106,6 @@
76
106
 
77
107
  == 0.3.0 / 2004-02-01 Martin Povolny <martin@solnet.cz>
78
108
 
79
- * libxslt.c: added call to ruby_init_xslt_transform_context() to make it
109
+ * libxslt.c: added call to ruby_init_xslt_transform_context() to make it
80
110
  work on ruby1.8
81
111
 
data/LICENSE CHANGED
@@ -3,19 +3,19 @@
3
3
  Copyright (c) 2002-2006 Sean Chittenden <sean@chittenden.org> and contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
- this software and associated documentation files (the "Software"), to deal in
7
- the Software without restriction, including without limitation the rights to
8
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
9
  of the Software, and to permit persons to whom the Software is furnished to do
10
10
  so, subject to the following conditions:
11
11
 
12
12
  The above copyright notice and this permission notice shall be included in all
13
13
  copies or substantial portions of the Software.
14
14
 
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
@@ -8,7 +8,7 @@ toolkit. It is free software, released under the MIT License.
8
8
 
9
9
  == Requirements
10
10
 
11
- libxslt-ruby requires Ruby 1.8.4 or higher. It is dependent on
11
+ libxslt-ruby requires Ruby 1.8.4 or higher. It is dependent on
12
12
  the following libraries to function properly:
13
13
 
14
14
  * libm (math routines: very standard)
@@ -24,7 +24,7 @@ includes an already built extension.
24
24
 
25
25
  !!!NOTE!!! The libxml-ruby and libxslt-ruby bindings must absolutely, positively,
26
26
  without a doubt share the same libxml2 library. This is because libxslt modifies
27
- XML documents created by libxml2. If there are two copies of libxml2 on your
27
+ XML documents created by libxml2. If there are two copies of libxml2 on your
28
28
  system, then when XML documents allocated in copy #1 are manipulated by copy #2,
29
29
  a segmentation fault will occur. So make sure that your system has only one copy of libxml2
30
30
  installed.
@@ -36,13 +36,13 @@ The easiest way to install libxslt-ruby is via Ruby Gems. To install:
36
36
 
37
37
  <tt>gem install libxslt-ruby</tt>
38
38
 
39
- If you are running Windows, make sure to install the Win32 RubyGem which
39
+ If you are running Windows, make sure to install the Win32 RubyGem which
40
40
  includes an already built binary file. The binary is built against
41
41
  libxml2 version 2.6.32, iconv version 1.11 and libxslt version 1.1.24.
42
42
  Binaries for libxml2 and iconv are provided in the libxml-ruby bindings,
43
- while a binary for libxslt is provided in the libxslt-ruby bindings.
43
+ while a binary for libxslt is provided in the libxslt-ruby bindings.
44
44
 
45
- The Windows binaries are biult with MingW. The gem also includes
45
+ The Windows binaries are biult with MingW. The gem also includes
46
46
  a Microsoft VC++ 2005 solution. If you wish to run a debug version
47
47
  of libxml-ruby on Windows, then it is highly recommended
48
48
  you use VC++.
@@ -51,12 +51,12 @@ you use VC++.
51
51
  == USAGE
52
52
 
53
53
  For in-depth information about using libxslt-ruby please refer
54
- to its online Rdoc documentation.
54
+ to its online Rdoc documentation.
55
55
 
56
56
  All libxslt classes are in the LibXSLT::XSLT module. The simplest
57
- way to use libxslt is to require 'xslt'. This will mixin the
58
- LibXML and LibXSLT modules into the global namespace, allowing you to
59
- write code like this:
57
+ way to use libxslt is to require 'xslt'. This will mixin the
58
+ LibXML and LibXSLT modules into the global namespace, allowing you to
59
+ write code like this:
60
60
 
61
61
  require 'xslt'
62
62
  document = XML::Document.new
@@ -78,10 +78,10 @@ Given an XML file like:
78
78
 
79
79
  <?xml version="1.0" encoding="UTF-8"?>
80
80
  <?xml-stylesheet href="fuzface.xsl" type="text/xsl"?>
81
-
81
+
82
82
  <commentary>
83
83
  <meta>
84
- <author>
84
+ <author>
85
85
  <first_name>Sean</first_name>
86
86
  <last_name>Chittenden</last_name>
87
87
  <email>sean@chittenden.org</email>
@@ -91,7 +91,7 @@ Given an XML file like:
91
91
  <id>$Id$</id> <title>Fuzface...</title>
92
92
  <subtitle>The Internet's a big place and here's some proof...</subtitle>
93
93
  </meta>
94
-
94
+
95
95
  <body>
96
96
  <para>
97
97
  I think it's a tragedy that I'm going to start off my new
@@ -111,21 +111,21 @@ And an XSLT file like this:
111
111
  <xsl:element name="head">
112
112
  <xsl:element name="title">Ramblings - <xsl:value-of select="commentary/meta/title" /> - <xsl:value-of select="commentary/meta/subtitle" /></xsl:element>
113
113
  </xsl:element>
114
-
114
+
115
115
  <xsl:element name="body">
116
116
  <xsl:element name="h1"><xsl:value-of select="commentary/meta/title" /></xsl:element>
117
117
  <xsl:element name="h3"><xsl:value-of select="commentary/meta/subtitle" /></xsl:element>
118
118
  By: <xsl:value-of select="commentary/meta/author/first_name" /> <xsl:value-of select="commentary/meta/author/last_name" /><xsl:element name="br" />
119
119
  Date: <xsl:value-of select="commentary/meta/date" /><xsl:element name="br" />
120
-
120
+
121
121
  <xsl:for-each select="./commentary/body">
122
122
  <xsl:apply-templates />
123
123
  </xsl:for-each>
124
-
124
+
125
125
  </xsl:element>
126
126
  </xsl:element>
127
127
  </xsl:template>
128
-
128
+
129
129
  <xsl:template match="para">
130
130
  <xsl:element name="p">
131
131
  <xsl:value-of select="." />
@@ -136,7 +136,7 @@ And an XSLT file like this:
136
136
  We can easily transform the XML with the following ruby code:
137
137
 
138
138
  require 'xslt'
139
-
139
+
140
140
  # Create a new XSL Transform
141
141
  stylesheet_doc = XML::Document.file('files/fuzface.xsl')
142
142
  stylesheet = LibXSLT::Stylesheet.new(stylesheet_doc)
@@ -144,7 +144,7 @@ We can easily transform the XML with the following ruby code:
144
144
  # Transform a xml document
145
145
  xml_doc = XML::Document.file('files/fuzface.xml')
146
146
  result = stylesheet.apply(xml_doc)
147
-
147
+
148
148
  You can then print, save or manipulate the returned document.
149
149
 
150
150
  == License
@@ -161,4 +161,4 @@ You can find the latest documentation at:
161
161
  == MORE INFORMATION
162
162
 
163
163
  For more information please refer to the documentation. If you have any
164
- questions, please send email to libxml-devel@rubyforge.org.
164
+ questions, please send email to libxml-devel@rubyforge.org.
data/Rakefile CHANGED
@@ -3,7 +3,7 @@
3
3
  require "rubygems"
4
4
  require "rake/extensiontask"
5
5
  require "rake/testtask"
6
- require 'hanna/rdoctask'
6
+ require 'rdoc/task'
7
7
  require "grancher/task"
8
8
  require "yaml"
9
9
 
@@ -13,19 +13,33 @@ SO_NAME = "libxslt_ruby"
13
13
  # Read the spec file
14
14
  spec = Gem::Specification.load("#{GEM_NAME}.gemspec")
15
15
 
16
- # Setup compile tasks
16
+ # Setup compile tasks. Configuration can be passed via EVN.
17
+ # Example:
18
+ # rake compile with_xml2_include=C:/MinGW/local/include/libxml2
19
+ # with_xslt_include=C:/MinGW/local/include/libxslt
20
+ # with_exslt_include=C:/MinGW/local/include/libexslt
17
21
  Rake::ExtensionTask.new do |ext|
18
22
  ext.gem_spec = spec
19
23
  ext.name = SO_NAME
20
24
  ext.ext_dir = "ext/libxslt"
21
25
  ext.lib_dir = "lib/#{RUBY_VERSION.sub(/\.\d$/, '')}"
22
- ext.config_options << "--with-xml2-include=C:/MinGW/local/include/libxml2"
23
- ext.config_options << "--with-xslt-include=C:/MinGW/local/include/libxslt"
24
- ext.config_options << "--with-exslt-include=C:/MinGW/local/include/libexslt"
26
+
27
+ ENV.each do |key, val|
28
+ next unless key =~ /\Awith_(\w+)\z/i
29
+ puts key
30
+ puts val
31
+ opt = $1.downcase.tr('_', '-')
32
+
33
+ if File.directory?(path = File.expand_path(val))
34
+ ext.config_options << "--with-#{opt}=#{path}"
35
+ else
36
+ warn "No such directory: #{opt}: #{path}"
37
+ end
38
+ end
25
39
  end
26
40
 
27
41
  # Setup generic gem
28
- Rake::GemPackageTask.new(spec) do |pkg|
42
+ Gem::PackageTask.new(spec) do |pkg|
29
43
  pkg.package_dir = 'pkg'
30
44
  pkg.need_tar = false
31
45
  end
@@ -39,12 +53,13 @@ if RUBY_PLATFORM.match(/win32|mingw32/)
39
53
  win_spec = spec.clone
40
54
  win_spec.platform = Gem::Platform::CURRENT
41
55
  win_spec.files += binaries.to_a
56
+ win_spec.instance_variable_set(:@cache_file, nil)
42
57
 
43
58
  # Unset extensions
44
59
  win_spec.extensions = nil
45
60
 
46
61
  # Rake task to build the windows package
47
- Rake::GemPackageTask.new(win_spec) do |pkg|
62
+ Gem::PackageTask.new(win_spec) do |pkg|
48
63
  pkg.package_dir = 'pkg'
49
64
  pkg.need_tar = false
50
65
  end
@@ -52,11 +67,11 @@ end
52
67
 
53
68
  # RDoc Task
54
69
  desc "Generate rdoc documentation"
55
- Rake::RDocTask.new("rdoc") do |rdoc|
70
+ RDoc::Task.new("rdoc") do |rdoc|
56
71
  rdoc.rdoc_dir = 'doc'
57
72
  rdoc.title = "libxml-xslt"
58
73
  # Show source inline with line numbers
59
- rdoc.options << "--inline-source" << "--line-numbers"
74
+ rdoc.options << "--line-numbers"
60
75
  # Make the readme file the start page for the generated html
61
76
  rdoc.options << '--main' << 'README'
62
77
  rdoc.rdoc_files.include('doc/*.rdoc',
@@ -70,5 +85,6 @@ end
70
85
  # Test Task
71
86
  Rake::TestTask.new do |t|
72
87
  t.libs << "test"
88
+ t.test_files = FileList['test/test*.rb'].exclude('test/test_suite.rb')
73
89
  t.verbose = true
74
90
  end
@@ -4,5 +4,4 @@
4
4
  #define HAVE_LIBXML_XMLVERSION_H 1
5
5
  #define HAVE_XSLT_H 1
6
6
  #define HAVE_EXSLT_H 1
7
- #define HAVE_LIBXML_RUBY_LIBXML_H 1
8
7
  #endif
@@ -21,7 +21,9 @@ dir_config('zlib')
21
21
  dir_config('xml2')
22
22
  dir_config('xslt')
23
23
  dir_config('exslt')
24
- dir_config('libxml-ruby')
24
+
25
+ # Ruby 1.9 has ruby/io.h instead of rubyio.h
26
+ have_header('ruby/io.h')
25
27
 
26
28
  # First get zlib
27
29
  unless have_library('z', 'inflate') or
@@ -109,38 +111,34 @@ unless (have_library('exslt','exsltRegisterAll') or
109
111
  end
110
112
 
111
113
  # Figure out where libxml-ruby is installed
112
- gem_specs = Gem.source_index.find_name('libxml-ruby')
113
- if gem_specs.empty?
114
+ unless gem_spec = Gem::Specification.find_by_name('libxml-ruby')
114
115
  crash(<<-EOL)
115
116
  libxml-ruby bindings must be installed
116
117
  EOL
117
118
  end
118
119
 
119
- gem_specs = gem_specs.sort_by {|spec| spec.version}.reverse
120
- libxml_ruby_path = gem_specs.first.full_gem_path
121
-
122
- $INCFLAGS += " -I#{libxml_ruby_path}/ext"
123
-
124
- unless have_header('libxml/ruby_libxml.h')
120
+ unless find_header("ruby_libxml.h", "#{gem_spec.full_gem_path}/ext/libxml")
125
121
  crash(<<-EOL)
126
122
  Need headers for libxml-ruby.
127
123
  EOL
128
124
  end
129
125
 
130
- if RUBY_PLATFORM.match(/win32|mingw32/)
131
- RUBY_VERSION =~ /(\d+.\d+)/
132
- $LIBPATH << File.join(libxml_ruby_path, "lib")
133
- $LIBPATH << File.join(libxml_ruby_path, "lib", $1)
134
-
135
- headers = ['iconv.h', 'libxml/ruby_libxml.h']
136
- unless have_library(':libxml_ruby.so', 'Init_libxml_ruby', headers)
137
- crash(<<-EOL)
138
- Need libxml-ruby
139
- Please install libxml-ruby or specify the path to the gem via:
140
- --with-libxml-ruby=/path/to/libxml-ruby gem
141
- EOL
142
- end
126
+
127
+ RUBY_VERSION =~ /(\d+.\d+)/
128
+ minor_version = $1
129
+ paths = ["#{gem_spec.full_gem_path}/lib", "#{gem_spec.full_gem_path}/lib/#{minor_version}"]
130
+
131
+ # Hack to make sure ruby library is *after* xml_ruby library
132
+ $LIBS += " #{$LIBRUBYARG_STATIC}"
133
+ unless find_library("xml_ruby", "Init_libxml_ruby", *paths) or
134
+ find_library(":libxml_ruby.so", "Init_libxml_ruby", *paths)
135
+ crash(<<-EOL)
136
+ Need libxml-ruby
137
+ Please install libxml-ruby or specify the path to the gem via:
138
+ --with-libxml-ruby=/path/to/libxml-ruby gem
139
+ EOL
143
140
  end
141
+ $LIBS.gsub!($LIBRUBYARG_STATIC,'')
144
142
 
145
143
  create_header()
146
144
  create_makefile("libxslt_ruby")
@@ -11,7 +11,7 @@ VALUE eXSLTError;
11
11
 
12
12
  /*
13
13
  * Document-class: LibXSLT::XSLT
14
- *
14
+ *
15
15
  * The libxslt gem provides Ruby language bindings for GNOME's Libxslt
16
16
  * toolkit. It is free software, released under the MIT License.
17
17
  *
@@ -22,26 +22,24 @@ VALUE eXSLTError;
22
22
  *
23
23
  * xml_doc = XML::Document.file('xml_file')
24
24
  * result = stylesheet.apply(xml_doc)
25
- *
26
25
  *
27
- */
26
+ */
28
27
 
29
28
  #ifdef RDOC_NEVER_DEFINED
30
29
  cLibXSLT = rb_define_module("XSLT");
31
30
  #endif
32
31
 
33
32
 
34
- #if defined(_WIN32)
35
- __declspec(dllexport)
36
- #endif
37
-
38
33
  void
39
34
  Init_libxslt_ruby(void) {
40
35
  LIBXML_TEST_VERSION;
41
-
36
+
42
37
  cLibXSLT = rb_define_module("LibXSLT");
43
38
  cXSLT = rb_define_module_under(cLibXSLT, "XSLT");
44
39
 
40
+ cXMLDocument = rb_const_get(rb_const_get(rb_const_get(rb_cObject,
41
+ rb_intern("LibXML")), rb_intern("XML")), rb_intern("Document"));
42
+
45
43
  rb_define_const(cXSLT, "MAX_DEPTH", INT2NUM(xsltMaxDepth));
46
44
  rb_define_const(cXSLT, "MAX_SORT", INT2NUM(XSLT_MAX_SORT));
47
45
  rb_define_const(cXSLT, "ENGINE_VERSION", rb_str_new2(xsltEngineVersion));
@@ -60,6 +58,7 @@ Init_libxslt_ruby(void) {
60
58
  eXSLTError = rb_define_class_under(cLibXSLT, "XSLTError", rb_eRuntimeError);
61
59
 
62
60
  ruby_init_xslt_stylesheet();
61
+ ruby_init_exslt();
63
62
 
64
63
  /* Now load exslt. */
65
64
  exsltRegisterAll();
@@ -6,17 +6,26 @@
6
6
  #define __RUBY_LIBXSLT_H__
7
7
 
8
8
  #include <ruby.h>
9
+ #if HAVE_RUBY_IO_H
10
+ #include <ruby/io.h>
11
+ #else
9
12
  #include <rubyio.h>
13
+ #endif
14
+
10
15
  #include <libxml/parser.h>
11
16
  #include <libxml/debugXML.h>
17
+ #include <ruby_libxml.h>
18
+
12
19
  #include <libxslt/extra.h>
13
20
  #include <libxslt/xslt.h>
14
21
  #include <libxslt/xsltInternals.h>
15
22
  #include <libxslt/transform.h>
16
23
  #include <libxslt/xsltutils.h>
24
+
17
25
  #include <libexslt/exslt.h>
18
26
 
19
27
  #include "ruby_xslt_stylesheet.h"
28
+ #include "ruby_exslt.h"
20
29
 
21
30
  #include "version.h"
22
31
 
@@ -27,5 +36,6 @@
27
36
  extern VALUE cLibXSLT;
28
37
  extern VALUE cXSLT;
29
38
  extern VALUE eXSLTError;
39
+ extern VALUE cXMLDocument;
30
40
 
31
41
  #endif
@@ -0,0 +1,148 @@
1
+ /* http://xmlsoft.org/XSLT/html/libxslt-extensions.html */
2
+
3
+ #include "libxslt.h"
4
+
5
+ /* Helper method to retrieve (and possibly initialize)
6
+ the module function registry hash for +namespace+ */
7
+ static VALUE
8
+ ruby_xslt_module_function_hash(VALUE namespace) {
9
+ VALUE ns_hash, func_hash;
10
+
11
+ if ((ns_hash = rb_ivar_get(cXSLT, rb_intern("@module_function_registry"))) == Qnil) {
12
+ ns_hash = rb_ivar_set(cXSLT, rb_intern("@module_function_registry"), rb_hash_new());
13
+ }
14
+
15
+ if ((func_hash = rb_hash_aref(ns_hash, namespace)) == Qnil) {
16
+ func_hash = rb_hash_aset(ns_hash, namespace, rb_hash_new());
17
+ }
18
+
19
+ return func_hash;
20
+ }
21
+
22
+ /* Helper method for xsltRegisterExtModuleFunction callback */
23
+ static void
24
+ ruby_xslt_module_function_callback(xmlXPathParserContextPtr ctxt, int nargs) {
25
+ VALUE callback, args[nargs];
26
+ const xmlChar *namespace, *name;
27
+ int i;
28
+
29
+ if (ctxt == NULL || ctxt->context == NULL) {
30
+ return;
31
+ }
32
+
33
+ namespace = ctxt->context->functionURI;
34
+ name = ctxt->context->function;
35
+
36
+ callback = rb_hash_aref(
37
+ ruby_xslt_module_function_hash(rb_str_new2((char *)namespace)),
38
+ rb_str_new2((char *)name)
39
+ );
40
+
41
+ if (callback == Qnil) {
42
+ rb_raise(rb_eArgError, "name `%s' not registered", name);
43
+ }
44
+
45
+ for (i = nargs - 1; i >= 0; i--) {
46
+ args[i] = rxml_xpath_to_value(ctxt->context, valuePop(ctxt));
47
+ }
48
+
49
+ valuePush(ctxt, rxml_xpath_from_value(
50
+ rb_funcall2(callback, rb_intern("call"), nargs, args)
51
+ ));
52
+ }
53
+
54
+ /* call-seq:
55
+ * XSLT.register_module_function(namespace, name) { ... } -> Proc or nil
56
+ *
57
+ * Registers +name+ as extension module function in +namespace+ with the
58
+ * block as callback. Returns the callback if successful, or +nil+ otherwise.
59
+ *
60
+ * The callback will be called with whatever XPath expression you pass
61
+ * into the function converted to a Ruby object. Its return value will
62
+ * be converted to an XPath expression again.
63
+ *
64
+ * Example:
65
+ *
66
+ * # register your extension function
67
+ * XSLT.register_module_function('http://ex.ns', 'ex-func') { |xp|
68
+ * xp.to_a.join('|').upcase
69
+ * }
70
+ *
71
+ * # then use it in your stylesheet
72
+ * <xsl:stylesheet ... xmlns:ex="http://ex.ns">
73
+ * ...
74
+ * <xsl:value-of select="ex:ex-func(.)" />
75
+ * <!-- the current node as upper case string -->
76
+ * </xsl:stylesheet>
77
+ */
78
+ static VALUE
79
+ ruby_xslt_register_module_function(VALUE class, VALUE namespace, VALUE name) {
80
+ VALUE callback;
81
+
82
+ if (!rb_block_given_p()) {
83
+ rb_raise(rb_eArgError, "no block given");
84
+ }
85
+
86
+ if (xsltRegisterExtModuleFunction(
87
+ BAD_CAST StringValuePtr(name),
88
+ BAD_CAST StringValuePtr(namespace),
89
+ ruby_xslt_module_function_callback
90
+ ) != 0) {
91
+ return Qnil;
92
+ }
93
+
94
+ callback = rb_block_proc();
95
+
96
+ rb_hash_aset(ruby_xslt_module_function_hash(namespace), name, callback);
97
+ return callback;
98
+ }
99
+
100
+ /* call-seq:
101
+ * XSLT.unregister_module_function(namespace, name) -> Proc or nil
102
+ *
103
+ * Unregisters +name+ as extension module function in +namespace+.
104
+ * Returns the previous callback if successful, or +nil+ otherwise.
105
+ */
106
+ static VALUE
107
+ ruby_xslt_unregister_module_function(VALUE class, VALUE namespace, VALUE name) {
108
+ VALUE func_hash, callback;
109
+
110
+ func_hash = ruby_xslt_module_function_hash(namespace);
111
+
112
+ if ((callback = rb_hash_aref(func_hash, name)) == Qnil) {
113
+ return Qnil;
114
+ }
115
+
116
+ if (xsltUnregisterExtModuleFunction(
117
+ BAD_CAST StringValuePtr(name),
118
+ BAD_CAST StringValuePtr(namespace)
119
+ ) != 0) {
120
+ return Qnil;
121
+ }
122
+
123
+ rb_hash_aset(func_hash, name, Qnil);
124
+ return callback;
125
+ }
126
+
127
+ /* call-seq:
128
+ * XSLT.registered_module_function?(namespace, name) -> true or false
129
+ *
130
+ * Returns +true+ if +name+ is currently registered as extension module
131
+ * function in +namespace+, or +false+ otherwise.
132
+ */
133
+ static VALUE
134
+ ruby_xslt_registered_module_function_p(VALUE class, VALUE namespace, VALUE name) {
135
+ return RTEST(rb_hash_aref(ruby_xslt_module_function_hash(namespace), name));
136
+ }
137
+
138
+ void
139
+ ruby_init_exslt() {
140
+ /* [HACK] Enclosing classes/modules for RDoc:
141
+ * cLibXSLT = rb_define_module("LibXSLT");
142
+ * cXSLT = rb_define_module_under(cLibXSLT, "XSLT");
143
+ */
144
+
145
+ rb_define_singleton_method(cXSLT, "register_module_function", ruby_xslt_register_module_function, 2);
146
+ rb_define_singleton_method(cXSLT, "unregister_module_function", ruby_xslt_unregister_module_function, 2);
147
+ rb_define_singleton_method(cXSLT, "registered_module_function?", ruby_xslt_registered_module_function_p, 2);
148
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef __RUBY_EXSLT__
2
+ #define __RUBY_EXSLT__
3
+
4
+ #include <libxslt/extensions.h>
5
+
6
+ void ruby_init_exslt(void);
7
+
8
+ #endif