saxon-rb 0.5.0-java → 0.6.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc90ab039f1169f43563e5036774ae66149c78c7b0027ea2b0cb72cafcd0b5e3
4
- data.tar.gz: 18490756712240e5d3869d73dd788ae980178ef3b79ffb41330a8e7db80c1b47
3
+ metadata.gz: 2e9afbc5a2644034bc285b3c3cd4e78f852b715d7a096ff8f7a6386730501598
4
+ data.tar.gz: fe9c135af6356690fcca7b4f1dc2d9656cce44018806c3b5f6c9f4b6407c576d
5
5
  SHA512:
6
- metadata.gz: d20fdd7e7b7fb7842d3d6059bb176903195fc911e46f4ffaecfa22d5dcc4e8919dadce8fe85feb5ab84045484d97f97ed3217330d77a4454a31c0b5efe1fc220
7
- data.tar.gz: c39dd5d7fa31cf2e58cddc002f51d218543f38eb270c10e618105eb559c1467cd338ca68abe317d4574427ef2461c1f3112c7f0acf0e2dd9f9463c67992b8660
6
+ metadata.gz: c59e0f986b8bbf4de77b18feba99a61c8e724df537679b0e674bc142a0d2b476026bb01579dcd2ec6e9b4f246493db3b892fbe7e997848eb06bf5c7bd8e2f5ea
7
+ data.tar.gz: 182d383aced898a376d37eaedb60ff80461910d3451e119f2bf6e97ebe37d8c64e600563ba968efec22f49ae02f025ec3725f00a2cb9af10813af8e20fc13100
data/README.md CHANGED
@@ -194,6 +194,47 @@ result = xslt.call_template('template-name', {
194
194
 
195
195
  Global and initial template parameters can be set at compiler creation time, compile time, or execution time. See [Setting parameters](#label-Setting+parameters) for details.
196
196
 
197
+ To serialize the document you can, of course, just call `#to_s` on the result:
198
+
199
+ ```ruby
200
+ result = xslt.apply_templates(input)
201
+ puts result.to_s #=> '<?xml version="1.0"...'
202
+ ```
203
+
204
+ You can also serialize directly to a file path or to any IO instance.
205
+
206
+ ```ruby
207
+ result = xslt.apply_templates(input)
208
+ result.serialize('/path/to/output.xml')
209
+
210
+ result_2 = xslt.apply_templates(input)
211
+ result_2.serialize($stderr)
212
+ ```
213
+
214
+ You can override serialization options that were set by `<xsl:output/>` in your XSLT:
215
+
216
+ ```ruby
217
+ result = xslt.apply_templates(input)
218
+ result.serialize('/path/to/output.xml') {
219
+ output_property[:indent] = 'yes'
220
+ }
221
+ ```
222
+
223
+ You can also obtain the result of the transform as an XDM Value:
224
+
225
+ ```ruby
226
+ result = xslt.apply_templates(input)
227
+ result.xdm_value #=> #<Saxon::XDM::Node...>
228
+ ```
229
+
230
+ You also have easy access to provide an instance of a class implementing Saxon's `net.sf.saxon.s9api.Destination` interface:
231
+
232
+ ```ruby
233
+ dom_document = javax.xml.parsers.DocumentBuilderFactory.newInstance.builder.newDocument
234
+ destination = Saxon::S9API::DOMDestination.new(dom_document)
235
+ result = xslt.apply_templates(input).to_destination(destination)
236
+ ```
237
+
197
238
  #### Setting parameters
198
239
 
199
240
  There are four kinds of parameters you can set: *Static parameters*, which are
@@ -44,7 +44,7 @@ module Saxon
44
44
  # @return [String] a serialization of the the input document
45
45
  def serialize(doc_node)
46
46
  s9_transformer = @s9_xslt_executable.load30
47
- serializer = Saxon::Serializer.new(s9_transformer.newSerializer)
47
+ serializer = Saxon::Serializer::Object.new(s9_transformer.newSerializer)
48
48
  serializer.serialize(doc_node.to_java)
49
49
  end
50
50
 
@@ -4,6 +4,7 @@ require 'saxon/configuration'
4
4
  require 'saxon/document_builder'
5
5
  require 'saxon/xpath'
6
6
  require 'saxon/xslt'
7
+ require 'saxon/serializer'
7
8
 
8
9
  module Saxon
9
10
  # Saxon::Processor wraps the S9API::Processor object. This is the object
@@ -82,6 +83,17 @@ module Saxon
82
83
  Saxon::XSLT::Compiler.create(self, &block)
83
84
  end
84
85
 
86
+ # Generate a new +Serializer+ for directly serializing XDM Values that uses
87
+ # this +Processor+. +Serializer+s are effectively one-shot objects, and
88
+ # shouldn't be reused.
89
+ #
90
+ # @yield the block passed will be called bound to the serializer instance. See
91
+ # {Saxon::Serializer::Object.create}
92
+ # @return [Saxon::Serializer::Object]
93
+ def serializer(&block)
94
+ Saxon::Serializer::Object.create(self, &block)
95
+ end
96
+
85
97
  # @return [net.sf.saxon.s9api.Processor] The underlying Saxon processor
86
98
  def to_java
87
99
  @s9_processor
@@ -0,0 +1,80 @@
1
+ require_relative '../s9api'
2
+ require_relative './output_properties'
3
+
4
+ module Saxon
5
+ module Serializer
6
+ # A Saxon Serializer to be used as a Destination for a transformation rather
7
+ # than being directly called with existing XDM objects
8
+ class Destination
9
+ include OutputProperties
10
+
11
+ attr_reader :s9_serializer, :invocation_lambda
12
+
13
+ # @api private
14
+ def initialize(s9_serializer, invocation_lambda, &block)
15
+ @s9_serializer, @invocation_lambda = s9_serializer, invocation_lambda
16
+ if block_given?
17
+ instance_exec(&block)
18
+ end
19
+ end
20
+
21
+ # @overload serialize(io)
22
+ # Serialize the transformation to an IO
23
+ # @param [File, IO] io The IO to serialize to
24
+ # @return [nil]
25
+ # @overload serialize(path)
26
+ # Serialize the transformation to file <tt>path</tt>
27
+ # @param [String, Pathname] path The path of the file to serialize to
28
+ # @return [nil]
29
+ # @overload serialize
30
+ # Serialize the transformation to a String
31
+ # @return [String] The serialized XdmValue
32
+ def serialize(io_or_path = nil)
33
+ case io_or_path
34
+ when nil
35
+ serialize_to_string
36
+ when String, Pathname
37
+ serialize_to_file(io_or_path)
38
+ else
39
+ serialize_to_io(io_or_path)
40
+ end
41
+ end
42
+
43
+ # @return [Saxon::S9API::Serializer] The underlying Saxon Serializer object
44
+ def to_java
45
+ s9_serializer
46
+ end
47
+
48
+ private
49
+
50
+ def run_transform!
51
+ invocation_lambda.call(self.to_java)
52
+ end
53
+
54
+ def serialize_to_string
55
+ str_encoding = output_property.fetch(:encoding, Encoding.default_internal || Encoding.default_external)
56
+ StringIO.open { |io|
57
+ io.binmode
58
+ set_output_io(io)
59
+ run_transform!
60
+ io.string.force_encoding(str_encoding)
61
+ }
62
+ end
63
+
64
+ def serialize_to_io(io)
65
+ set_output_io(io)
66
+ run_transform!
67
+ end
68
+
69
+ def set_output_io(io)
70
+ s9_serializer.setOutputStream(io.to_outputstream)
71
+ end
72
+
73
+ def serialize_to_file(path)
74
+ file = Java::JavaIO::File.new(path.to_s)
75
+ s9_serializer.setOutputFile(file)
76
+ run_transform!
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,93 @@
1
+ require_relative '../s9api'
2
+ require_relative './output_properties'
3
+ require 'stringio'
4
+
5
+ module Saxon
6
+ module Serializer
7
+ # A Saxon Serializer to be used directly with XDM Values rather than being
8
+ # called as a Destination for a transformation.
9
+ class Object
10
+ # Create a serializer from the passed in +Processor+. When called with a
11
+ # block, the block will be executed via instance-exec so that output
12
+ # properties can be set, e.g.
13
+ #
14
+ # Serializer::Object.create(processor) {
15
+ # output_property[:indent] = 'yes'
16
+ # }
17
+ #
18
+ # @param processor [Saxon::Processor] the processor to create this
19
+ # +Serializer::Object+ from
20
+ # @yield the passed block bound via instance-exec to the new serializer
21
+ def self.create(processor, &block)
22
+ new(processor.to_java.newSerializer, &block)
23
+ end
24
+
25
+ include OutputProperties
26
+
27
+ attr_reader :s9_serializer
28
+ private :s9_serializer
29
+
30
+ # @api private
31
+ def initialize(s9_serializer, &block)
32
+ @s9_serializer = s9_serializer
33
+ if block_given?
34
+ instance_exec(&block)
35
+ end
36
+ end
37
+
38
+ # @overload serialize(xdm_value, io)
39
+ # Serialize an XdmValue to an IO
40
+ # @param [Saxon::XdmValue] xdm_value The XdmValue to serialize
41
+ # @param [File, IO] io The IO to serialize to
42
+ # @return [nil]
43
+ # @overload serialize(xdm_value, path)
44
+ # Serialize an XdmValue to file <tt>path</tt>
45
+ # @param [Saxon::XdmValue] xdm_value The XdmValue to serialize
46
+ # @param [String, Pathname] path The path of the file to serialize to
47
+ # @return [nil]
48
+ # @overload serialize(xdm_value)
49
+ # Serialize an XdmValue to a String
50
+ # @param [Saxon::XdmValue] xdm_value The XdmValue to serialize
51
+ # @return [String] The serialized XdmValue
52
+ def serialize(xdm_value, io_or_path = nil)
53
+ case io_or_path
54
+ when nil
55
+ serialize_to_string(xdm_value)
56
+ when String, Pathname
57
+ serialize_to_file(xdm_value, io_or_path)
58
+ else
59
+ serialize_to_io(xdm_value, io_or_path)
60
+ end
61
+ end
62
+
63
+ # @return [Saxon::S9API::Serializer] The underlying Saxon Serializer object
64
+ def to_java
65
+ s9_serializer
66
+ end
67
+
68
+ private
69
+
70
+ def serialize_to_io(xdm_value, io)
71
+ s9_serializer.setOutputStream(io.to_outputstream)
72
+ s9_serializer.serializeXdmValue(xdm_value.to_java)
73
+ nil
74
+ end
75
+
76
+ def serialize_to_string(xdm_value)
77
+ str_encoding = output_property.fetch(:encoding, Encoding.default_internal || Encoding.default_external)
78
+ StringIO.open { |io|
79
+ io.binmode
80
+ serialize_to_io(xdm_value, io)
81
+ io.string.force_encoding(str_encoding)
82
+ }
83
+ end
84
+
85
+ def serialize_to_file(xdm_value, path)
86
+ file = Java::JavaIO::File.new(path.to_s)
87
+ s9_serializer.setOutputFile(file)
88
+ s9_serializer.serializeXdmValue(xdm_value.to_java)
89
+ nil
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,83 @@
1
+ module Saxon
2
+ module Serializer
3
+ # Manage access to the serialization properties of this serializer, with
4
+ # hash-like access.
5
+ #
6
+ # Properties can be set explicitly through this API, or via XSLT or XQuery
7
+ # serialization options like +<xsl:output>+.
8
+ #
9
+ # Properties set explicitly here will override properties set through the
10
+ # document by +<xsl:output>+.
11
+ module OutputProperties
12
+ # @return [Saxon::Serializer::OutputProperties] hash-like access to the Output Properties
13
+ def output_property
14
+ @output_property ||= OutputProperties::Accessor.new(s9_serializer)
15
+ end
16
+
17
+ # @api private
18
+ #
19
+ # The private wrapper class that manages getting and setting output
20
+ # properties on a Serializer in an idiomatic Ruby-like way.
21
+ class Accessor
22
+ # @api private
23
+ # Provides mapping between symbols and the underlying Saxon property
24
+ # instances
25
+ def self.output_properties
26
+ @output_properties ||= Hash[
27
+ Saxon::S9API::Serializer::Property.values.map { |property|
28
+ qname = property.getQName
29
+ key = [
30
+ qname.getPrefix,
31
+ qname.getLocalName.tr('-', '_')
32
+ ].reject { |str| str == '' }.join('_').to_sym
33
+ [key, property]
34
+ }
35
+ ]
36
+ end
37
+
38
+ attr_reader :s9_serializer
39
+
40
+ # @api private
41
+ def initialize(s9_serializer)
42
+ @s9_serializer = s9_serializer
43
+ end
44
+
45
+ # @param [Symbol, Saxon::S9API::Serializer::Property] property The property to fetch
46
+ def [](property)
47
+ s9_serializer.getOutputProperty(resolved_property(property))
48
+ end
49
+
50
+ # @param [Symbol, Saxon::S9API::Serializer::Property] property The property to set
51
+ # @param [String] value The string value of the property
52
+ def []=(property, value)
53
+ s9_serializer.setOutputProperty(resolved_property(property), value)
54
+ end
55
+
56
+ # @overload fetch(property)
57
+ # @param [Symbol, Saxon::S9API::Serializer::Property] property The property to fetch
58
+ # @overload fetch(property, default)
59
+ # @param property [Symbol, Saxon::S9API::Serializer::Property] The property to fetch
60
+ # @param default [Object] The value to return if the property is unset
61
+ def fetch(property, default = nil)
62
+ explicit_value = self[property]
63
+ if explicit_value.nil? && !default.nil?
64
+ default
65
+ else
66
+ explicit_value
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def resolved_property(property_key)
73
+ case property_key
74
+ when Symbol
75
+ self.class.output_properties.fetch(property_key)
76
+ else
77
+ property_key
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -1,143 +1,9 @@
1
- require 'saxon/s9api'
2
- require 'stringio'
1
+ require_relative './serializer/destination.rb'
2
+ require_relative './serializer/object.rb'
3
3
 
4
4
  module Saxon
5
5
  # Serialize XDM objects.
6
- class Serializer
7
- # Manage access to the serialization properties of this serializer, with
8
- # hash-like access.
9
- #
10
- # Properties can be set explicitly through this API, or via XSLT or XQuery
11
- # serialization options like `<xsl:output>`.
12
- #
13
- # Properties set explicitly here will override properties set through the
14
- # document like `<xsl:output>`.
15
- class OutputProperties
16
- # @api private
17
- # Provides mapping between symbols and the underlying Saxon property
18
- # instances
19
- def self.output_properties
20
- @output_properties ||= Hash[
21
- Saxon::S9API::Serializer::Property.values.map { |property|
22
- qname = property.getQName
23
- key = [
24
- qname.getPrefix,
25
- qname.getLocalName.tr('-', '_')
26
- ].reject { |str| str == '' }.join('_').to_sym
27
- [key, property]
28
- }
29
- ]
30
- end
31
-
32
- attr_reader :s9_serializer
33
-
34
- # @api private
35
- def initialize(s9_serializer)
36
- @s9_serializer = s9_serializer
37
- end
38
-
39
- # @param [Symbol, Saxon::S9API::Serializer::Property] property The property to fetch
40
- def [](property)
41
- s9_serializer.getOutputProperty(resolved_property(property))
42
- end
43
-
44
- # @param [Symbol, Saxon::S9API::Serializer::Property] property The property to set
45
- # @param [String] value The string value of the property
46
- def []=(property, value)
47
- s9_serializer.setOutputProperty(resolved_property(property), value)
48
- end
49
-
50
- # @overload fetch(property)
51
- # @param [Symbol, Saxon::S9API::Serializer::Property] property The property to fetch
52
- # @overload fetch(property, default)
53
- # @param property [Symbol, Saxon::S9API::Serializer::Property] The property to fetch
54
- # @param default [Object] The value to return if the property is unset
55
- def fetch(property, default = nil)
56
- explicit_value = self[property]
57
- if explicit_value.nil? && !default.nil?
58
- default
59
- else
60
- explicit_value
61
- end
62
- end
63
-
64
- private
65
- def resolved_property(property_key)
66
- case property_key
67
- when Symbol
68
- self.class.output_properties.fetch(property_key)
69
- else
70
- property_key
71
- end
72
- end
73
- end
74
-
75
- attr_reader :s9_serializer
76
- private :s9_serializer
77
-
78
- # @api private
79
- def initialize(s9_serializer)
80
- @s9_serializer = s9_serializer
81
- end
82
-
83
- # @return [Saxon::Serializer::OutputProperties] hash-like access to the Output Properties
84
- def output_property
85
- @output_property ||= OutputProperties.new(s9_serializer)
86
- end
87
-
88
- # @overload serialize(xdm_value, io)
89
- # Serialize an XdmValue to an IO
90
- # @param [Saxon::XdmValue] xdm_value The XdmValue to serialize
91
- # @param [File, IO] io The IO to serialize to
92
- # @return [nil]
93
- # @overload serialize(xdm_value, path)
94
- # Serialize an XdmValue to file <tt>path</tt>
95
- # @param [Saxon::XdmValue] xdm_value The XdmValue to serialize
96
- # @param [String, Pathname] path The path of the file to serialize to
97
- # @return [nil]
98
- # @overload serialize(xdm_value)
99
- # Serialize an XdmValue to a String
100
- # @param [Saxon::XdmValue] xdm_value The XdmValue to serialize
101
- # @return [String] The serialized XdmValue
102
- def serialize(xdm_value, io_or_path = nil)
103
- case io_or_path
104
- when nil
105
- serialize_to_string(xdm_value)
106
- when String, Pathname
107
- serialize_to_file(xdm_value, io_or_path)
108
- else
109
- serialize_to_io(xdm_value, io_or_path)
110
- end
111
- end
112
-
113
- # @return [Saxon::S9API::Serializer] The underlying Saxon Serializer object
114
- def to_java
115
- s9_serializer
116
- end
117
-
118
- private
119
-
120
- def serialize_to_io(xdm_value, io)
121
- s9_serializer.setOutputStream(io.to_outputstream)
122
- s9_serializer.serializeXdmValue(xdm_value.to_java)
123
- nil
124
- end
125
-
126
- def serialize_to_string(xdm_value)
127
- str_encoding = output_property.fetch(:encoding, Encoding.default_internal || Encoding.default_external)
128
- StringIO.open { |io|
129
- io.binmode
130
- serialize_to_io(xdm_value, io)
131
- io.string.force_encoding(str_encoding)
132
- }
133
- end
134
-
135
- def serialize_to_file(xdm_value, path)
136
- file = Java::JavaIO::File.new(path)
137
- s9_serializer.setOutputFile(file)
138
- s9_serializer.serializeXdmValue(xdm_value.to_java)
139
- nil
140
- end
6
+ module Serializer
141
7
  end
142
8
  end
143
9
 
data/lib/saxon/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Saxon
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -33,9 +33,10 @@ module Saxon
33
33
  @node_name = node_name.nil? ? nil : Saxon::QName.new(node_name)
34
34
  end
35
35
 
36
- # What kind of node this is. Returns one of +:element+, +:text+,
37
- # +:attribute+, +:namespace+, +:comment+, +:processing_instruction+, or
38
- # +:comment+
36
+ # What kind of node this is. Returns one of +:document+, +:element+,
37
+ # +:text+, +:attribute+, +:namespace+, +:comment+,
38
+ # +:processing_instruction+, or +:comment+
39
+ #
39
40
  # @return [Symbol] the kind of node this is
40
41
  def node_kind
41
42
  @node_kind ||= case s9_xdm_node.nodeKind
@@ -1,5 +1,6 @@
1
1
  require 'forwardable'
2
2
  require_relative 'evaluation_context'
3
+ require_relative 'invocation'
3
4
  require_relative '../serializer'
4
5
  require_relative '../xdm'
5
6
  require_relative '../qname'
@@ -96,7 +97,7 @@ module Saxon
96
97
  # to pass to the first template matched. Setting already-defined
97
98
  # parameters will replace their value for this invocation of the XSLT
98
99
  # only, it won't affect the {XSLT::Compiler}'s context.
99
- # @return [Saxon::XSLT::Result] the transformation result
100
+ # @return [Saxon::XSLT::Invocation] the transformation result
100
101
  def apply_templates(source, opts = {})
101
102
  transformation(opts).apply_templates(source)
102
103
  end
@@ -130,7 +131,7 @@ module Saxon
130
131
  # to pass to the first template matched. Setting already-defined
131
132
  # parameters will replace their value for this invocation of the XSLT
132
133
  # only, it won't affect the {XSLT::Compiler}'s context.
133
- # @return [Saxon::XSLT::Result] the transformation result
134
+ # @return [Saxon::XSLT::Invocation] the transformation result
134
135
  def call_template(template_name = nil, opts = {})
135
136
  transformation(opts).call_template(template_name)
136
137
  end
@@ -155,14 +156,14 @@ module Saxon
155
156
  # Additional global parameters to set. Setting already-defined
156
157
  # parameters will replace their value for this invocation of the XSLT
157
158
  # only, it won't affect the {XSLT::Compiler}'s context.
158
- # @return [Saxon::XSLT::Result] the transformation result
159
+ # @return [Saxon::XSLT::Invocation] the transformation result
159
160
  def call_function(function_name, opts = {})
160
161
  args = opts.fetch(:args, [])
161
162
  transformation(opts.reject { |k, v| k == :args }).call_function(function_name, args)
162
163
  end
163
164
 
164
165
  # @return [net.sf.saxon.s9api.XsltExecutable] the underlying Saxon
165
- # <tt>XsltExecutable</tt>
166
+ # +XsltExecutable+
166
167
  def to_java
167
168
  @s9_xslt_executable
168
169
  end
@@ -213,6 +214,7 @@ module Saxon
213
214
  @default_initial_template ||= Saxon::QName.clark('{http://www.w3.org/1999/XSL/Transform}initial-template')
214
215
  end
215
216
 
217
+ # @api private
216
218
  def initialize(args)
217
219
  @s9_transformer = args.fetch(:s9_transformer)
218
220
  @destination = args.fetch(:destination, nil)
@@ -225,57 +227,48 @@ module Saxon
225
227
  # Apply templates to Source, using all the context set up when we were
226
228
  # created.
227
229
  def apply_templates(source)
228
- transformation_result(:applyTemplates, source)
230
+ transformation_invocation(:applyTemplates, source.to_java)
229
231
  end
230
232
 
231
233
  # Call the named template, using all the context set up when we were
232
234
  # created.
233
235
  def call_template(template_name)
234
- transformation_result(:callTemplate, resolve_template_name(template_name))
236
+ transformation_invocation(:callTemplate, resolve_template_name(template_name))
235
237
  end
236
238
 
237
239
  # Call the named function, using all the context set up when we were
238
240
  # created.
239
241
  def call_function(function_name, args)
240
242
  function_name = Saxon::QName.resolve(function_name).to_java
241
- args = function_args(args)
242
- call_function_result(function_name, args)
243
+ transformation_invocation(:callFunction, function_name, function_args(args))
243
244
  end
244
245
 
245
246
  private
246
247
 
247
- def transformation_result(invocation_method, invocation_arg)
248
+ def transformation_invocation(invocation_method, *invocation_args)
248
249
  set_opts!
249
- transformer_args = [invocation_method, invocation_arg.to_java, destination].compact
250
- Result.new(result_xdm_value(s9_transformer.send(*transformer_args)), s9_transformer)
250
+ XSLT::Invocation.new(s9_transformer, invocation_lambda(invocation_method, invocation_args), raw?)
251
251
  end
252
252
 
253
- def call_function_result(name, args)
254
- set_opts!
255
- Result.new(result_xdm_value(s9_transformer.callFunction(*[name, args, destination].compact)), s9_transformer)
256
- end
257
-
258
- def result_xdm_value(transformer_return_value)
259
- XDM.Value(
260
- transformer_return_value.nil? ? destination.getXdmNode : transformer_return_value
261
- )
253
+ def invocation_lambda(invocation_method, invocation_args)
254
+ ->(destination) {
255
+ if destination.nil?
256
+ s9_transformer.send(invocation_method, *invocation_args)
257
+ else
258
+ s9_transformer.send(invocation_method, *invocation_args, destination.to_java)
259
+ end
260
+ }
262
261
  end
263
262
 
264
263
  def resolve_template_name(template_name)
265
- return self.class.default_initial_template if template_name.nil?
266
- Saxon::QName.resolve(template_name)
264
+ return self.class.default_initial_template.to_java if template_name.nil?
265
+ Saxon::QName.resolve(template_name).to_java
267
266
  end
268
267
 
269
268
  def function_args(args = [])
270
269
  args.map { |val| Saxon::XDM.Value(val).to_java }.to_java(S9API::XdmValue)
271
270
  end
272
271
 
273
- def destination
274
- @destination ||= begin
275
- Saxon::S9API::XdmDestination.new unless raw?
276
- end
277
- end
278
-
279
272
  def set_opts!
280
273
  opts.each do |opt, value|
281
274
  raise BadOptionError, opt unless VALID_OPTS.include?(opt)
@@ -312,24 +305,6 @@ module Saxon
312
305
  end
313
306
  end
314
307
 
315
- # Represents the result of a transformation, providing a simple default
316
- # serializer as well
317
- class Result
318
- attr_reader :xdm_value
319
-
320
- # @api private
321
- def initialize(xdm_value, s9_transformer)
322
- @xdm_value, @s9_transformer = xdm_value, s9_transformer
323
- end
324
-
325
- # Serialize the result to a string using the options specified in
326
- # +<xsl:output/>+ in the XSLT
327
- def to_s
328
- serializer = Serializer.new(@s9_transformer.newSerializer)
329
- serializer.serialize(xdm_value.to_java)
330
- end
331
- end
332
-
333
308
  # Raised if a bad option name is passed in the options hash to
334
309
  # Executable#apply_templates et al
335
310
  class BadOptionError < StandardError
@@ -0,0 +1,96 @@
1
+ require_relative '../serializer'
2
+ require_relative '../xdm/value'
3
+
4
+
5
+ module Saxon
6
+ module XSLT
7
+ # Represents the invocation of a compiled and loaded transformation,
8
+ # providing an idiomatic way to send the result a transformation to a
9
+ # particular Destination, or to serialize it directly to a file, string, or
10
+ # IO.
11
+ class Invocation
12
+ attr_reader :s9_transformer, :invocation_lambda
13
+
14
+ # @api private
15
+ def initialize(s9_transformer, invocation_lambda, raw)
16
+ @s9_transformer, @invocation_lambda, @raw = s9_transformer, invocation_lambda, raw
17
+ end
18
+
19
+ # Serialize the result to a string using the options specified in
20
+ # +<xsl:output/>+ in the XSLT
21
+ #
22
+ # @return [String] the serialized result of the transformation
23
+ def to_s
24
+ serializer_destination.serialize
25
+ end
26
+
27
+ # Serialize the result of the transformation. When called with a
28
+ # block, the block will be executed via instance-exec so that output
29
+ # properties can be set, e.g.
30
+ #
31
+ # result.serialize {
32
+ # output_property[:indent] = 'yes'
33
+ # }
34
+ #
35
+ # @overload serialize(io)
36
+ # Serialize the transformation to an IO
37
+ # @param [File, IO] io The IO to serialize to
38
+ # @return [nil]
39
+ # @yield the passed block bound via instance-exec to the new serializer
40
+ # @overload serialize(path)
41
+ # Serialize the transformation to file <tt>path</tt>
42
+ # @param [String, Pathname] path The path of the file to serialize to
43
+ # @return [nil]
44
+ # @yield the passed block bound via instance-exec to the new serializer
45
+ # @overload serialize
46
+ # Serialize the transformation to a String
47
+ # @return [String] The serialized XdmValue
48
+ def serialize(path_or_io = nil, &block)
49
+ serializer_destination(&block).serialize(path_or_io)
50
+ end
51
+
52
+ # Return the result of the transformation as an XDM Value, either as it is
53
+ # returned (if the XSLT::Executable was created with :raw => true), or
54
+ # wrapped in a Document node and sequence normalized.
55
+ #
56
+ # @return [Saxon::XDM::Value] the XDM value returned by the transformation
57
+ def xdm_value
58
+ if raw?
59
+ XDM.Value(invocation_lambda.call(nil))
60
+ else
61
+ invocation_lambda.call(s9_xdm_destination)
62
+ XDM.Value(s9_xdm_destination.getXdmNode)
63
+ end
64
+ end
65
+
66
+ # Send the result of the transformation to the supplied Destination
67
+ #
68
+ # @param destination [net.sf.saxon.s9api.Destination] the Saxon
69
+ # destination to use
70
+ # @return [nil]
71
+ def to_destination(s9_destination)
72
+ invocation_lambda.call(s9_destination)
73
+ nil
74
+ end
75
+
76
+ # Whether the transformation was invoked as a 'raw' transformation, where
77
+ # an XDM Value result will be returned without being wrapped in a Document
78
+ # node, and without sequence normalization.
79
+ #
80
+ # @return [Boolean] whether the transformation was invoked 'raw' or not
81
+ def raw?
82
+ @raw
83
+ end
84
+
85
+ private
86
+
87
+ def serializer_destination(&block)
88
+ Saxon::Serializer::Destination.new(s9_transformer.newSerializer, invocation_lambda, &block)
89
+ end
90
+
91
+ def s9_xdm_destination
92
+ @s9_xdm_destination ||= Saxon::S9API::XdmDestination.new
93
+ end
94
+ end
95
+ end
96
+ end
data/saxon-rb.gemspec CHANGED
@@ -34,6 +34,6 @@ It aims to provide an idiomatic Ruby wrapper around all of Saxon's features.}
34
34
  spec.add_development_dependency 'addressable', '~> 2.4.0'
35
35
  spec.add_development_dependency 'webmock', '~> 2.3.2'
36
36
  spec.add_development_dependency 'yard', '~> 0.9.12'
37
- spec.add_development_dependency 'simplecov', '~> 0.15'
37
+ spec.add_development_dependency 'simplecov', '~> 0.17.1'
38
38
  spec.add_development_dependency 'rspec_junit_formatter'
39
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saxon-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: java
6
6
  authors:
7
7
  - Matt Patterson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-02 00:00:00.000000000 Z
11
+ date: 2020-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -127,7 +127,7 @@ dependencies:
127
127
  requirements:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: '0.15'
130
+ version: 0.17.1
131
131
  name: simplecov
132
132
  prerelease: false
133
133
  type: :development
@@ -135,7 +135,7 @@ dependencies:
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '0.15'
138
+ version: 0.17.1
139
139
  - !ruby/object:Gem::Dependency
140
140
  requirement: !ruby/object:Gem::Requirement
141
141
  requirements:
@@ -191,6 +191,9 @@ files:
191
191
  - lib/saxon/s9api.rb
192
192
  - lib/saxon/sequence_type.rb
193
193
  - lib/saxon/serializer.rb
194
+ - lib/saxon/serializer/destination.rb
195
+ - lib/saxon/serializer/object.rb
196
+ - lib/saxon/serializer/output_properties.rb
194
197
  - lib/saxon/source.rb
195
198
  - lib/saxon/version.rb
196
199
  - lib/saxon/xdm.rb
@@ -213,6 +216,7 @@ files:
213
216
  - lib/saxon/xslt/compiler.rb
214
217
  - lib/saxon/xslt/evaluation_context.rb
215
218
  - lib/saxon/xslt/executable.rb
219
+ - lib/saxon/xslt/invocation.rb
216
220
  - saxon-rb.gemspec
217
221
  homepage: https://github.com/fidothe/saxon-rb
218
222
  licenses: