saxon 0.1.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.
@@ -0,0 +1,68 @@
1
+ require_relative '../item_type'
2
+ require_relative '../occurrence_indicator'
3
+
4
+ module Saxon
5
+ module XPath
6
+ # Represents an XPath variable declaration in the static context of a compiled XPath, providing an idiomatic Ruby way to deal with these.
7
+ class VariableDeclaration
8
+ # @return [Saxon::QName]
9
+ attr_reader :qname
10
+ # @return [Saxon::ItemType]
11
+ attr_reader :item_type
12
+ # @return [net.sf.saxon.s9api.OccurrenceIndicator]
13
+ attr_reader :occurrences
14
+
15
+ # @param opts [Hash]
16
+ # @option opts [Saxon::QName] :qname The name of the variable as a {Saxon::QName}
17
+ def initialize(opts = {})
18
+ raise VariableDeclarationError, opts.keys if opts.keys.length > 2
19
+ @qname = opts.fetch(:qname)
20
+ @item_type, @occurrences = extract_type_decl(opts.reject { |k, v| k == :qname })
21
+ end
22
+
23
+ # VariableDeclarations compare equal if their qname, item_type, and occurrences are equal
24
+ # @param other [Saxon::VariableDeclaration]
25
+ # @return [Boolean]
26
+ def ==(other)
27
+ VariableDeclaration === other && qname == other.qname && item_type == other.item_type && occurrences == other.occurrences
28
+ end
29
+
30
+ # @api private
31
+ def compiler_args
32
+ [qname.to_java, item_type.to_java, occurrences]
33
+ end
34
+
35
+ private
36
+
37
+ def self.valid_opt_keys
38
+ @valid_opt_keys ||= [:qname] + Saxon::OccurrenceIndicator.indicator_names
39
+ end
40
+
41
+ def extract_type_decl(type_decl)
42
+ raise VariableDeclarationError, type_decl.keys if type_decl.length > 1
43
+ unless (type_decl.keys - Saxon::OccurrenceIndicator.indicator_names).empty?
44
+ raise VariableDeclarationError, type_decl.keys
45
+ end
46
+
47
+ return [Saxon::ItemType.get_type('item()'), Saxon::OccurrenceIndicator.zero_or_more] if type_decl.empty?
48
+ occurrence, type = type_decl.first
49
+ [Saxon::ItemType.get_type(type), Saxon::OccurrenceIndicator.send(occurrence)]
50
+ end
51
+ end
52
+
53
+ # Raised when an attempt to declare a variable is made using an occurrence
54
+ # indicator that does not exist
55
+ class VariableDeclarationError < StandardError
56
+ attr_reader :keys
57
+
58
+ def initialize(keys)
59
+ @keys = keys
60
+ end
61
+
62
+ # reports allowable occurrence indicator keys and what was actually passed in
63
+ def to_s
64
+ "requires :qname, and optionally one of #{Saxon::OccurrenceIndicator.indicator_names}, was passed #{keys.join(', ')}"
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,8 @@
1
+ require_relative './xslt/compiler'
2
+
3
+ module Saxon
4
+ # Classes for compiling, configuring, and executing XSLT transformations
5
+ # against XDM nodes or documents
6
+ module XSLT
7
+ end
8
+ end
@@ -0,0 +1,61 @@
1
+ require 'forwardable'
2
+ require_relative './static_context'
3
+ # require_relative './executable'
4
+
5
+ module Saxon
6
+ module XSLT
7
+ # Compiles XSLT stylesheets so they can be executed
8
+ class Compiler
9
+ # Create a new <tt>XSLT::Compiler</tt> using the supplied Processor.
10
+ # Passing a block gives access to a DSL for setting up the compiler's
11
+ # static context.
12
+ #
13
+ # @param processor [Saxon::Processor] the {Saxon::Processor} to use
14
+ # @yield An XSLT compiler DSL block
15
+ # @return [Saxon::XSLT::Compiler] the new compiler instance
16
+ def self.create(processor, &block)
17
+ static_context = XSLT::StaticContext.define(block)
18
+ new(processor.to_java, static_context)
19
+ end
20
+
21
+ extend Forwardable
22
+
23
+ attr_reader :static_context
24
+ private :static_context
25
+
26
+ # @api private
27
+ # @param s9_processor [net.sf.saxon.s9api.Processor] the Saxon
28
+ # <tt>Processor</tt> to wrap
29
+ # @param static_context [Saxon::XPath::StaticContext] the static context
30
+ # XPaths compiled using this compiler will have
31
+ def initialize(s9_processor, static_context)
32
+ @s9_processor, @static_context = s9_processor, static_context
33
+ end
34
+
35
+ def_delegators :static_context, :default_collation
36
+ # @!attribute [r] declared_collations
37
+ # @return [Hash<String => java.text.Collator>] declared collations as URI => Collator hash
38
+ # @!attribute [r] default_collation
39
+ # @return [String] the URI of the default declared collation
40
+
41
+ # @param expression [String] the expression to compile
42
+ # @return [Saxon::XSLT::Executable] the executable query
43
+ def compile(expression)
44
+ Saxon::XSLT::Executable.new(new_compiler.compile(expression), static_context)
45
+ end
46
+
47
+ def create(&block)
48
+ new_static_context = static_context.define(block)
49
+ self.class.new(@s9_processor, new_static_context)
50
+ end
51
+
52
+ private
53
+
54
+ def new_compiler
55
+ compiler = @s9_processor.newXsltCompiler
56
+ compiler.declareDefaultCollation(default_collation) unless default_collation.nil?
57
+ compiler
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,127 @@
1
+ require_relative 'static_context'
2
+ require_relative '../serializer'
3
+ require_relative '../xdm_value'
4
+ require_relative '../qname'
5
+
6
+ module Saxon
7
+ module XSLT
8
+ # Represents a compiled XPaGth query ready to be executed
9
+ class Executable
10
+ # @return [XSLT::StaticContext] the XPath's static context
11
+ attr_reader :static_context
12
+
13
+ # @api private
14
+ # @param s9_xslt_executable [net.sf.saxon.s9api.XsltExecutable] the
15
+ # Saxon compiled XPath object
16
+ # @param static_context [XPath::StaticContext] the XPath's static
17
+ # context
18
+ def initialize(s9_xslt_executable, static_context)
19
+ @s9_xslt_executable, @static_context = s9_xslt_executable, static_context
20
+ end
21
+
22
+ def apply_templates(source, opts = {})
23
+ transformation(opts).apply_templates(source)
24
+ end
25
+
26
+ def call_template(template_name, opts = {})
27
+ transformation(opts).call_template(template_name)
28
+ end
29
+
30
+ # @return [net.sf.saxon.s9api.XsltExecutable] the underlying Saxon
31
+ # <tt>XsltExecutable</tt>
32
+ def to_java
33
+ @s9_xslt_executable
34
+ end
35
+
36
+ private
37
+
38
+ def transformation(opts)
39
+ Transformation.new(opts.merge({
40
+ s9_transformer: @s9_xslt_executable.load30,
41
+ }))
42
+ end
43
+ end
44
+
45
+ class Result
46
+ attr_reader :xdm_value
47
+
48
+ def initialize(xdm_value, s9_transformer)
49
+ @xdm_value, @s9_transformer = xdm_value, s9_transformer
50
+ end
51
+
52
+ def to_s
53
+ serializer = Serializer.new(@s9_transformer.newSerializer)
54
+ serializer.serialize(xdm_value.to_java)
55
+ end
56
+ end
57
+
58
+ class Transformation
59
+ attr_reader :s9_transformer, :opts
60
+
61
+ def initialize(args)
62
+ @s9_transformer = args.fetch(:s9_transformer)
63
+ @destination = args.fetch(:destination, nil)
64
+ @opts = args.reject { |opt, _|
65
+ [:s9_transformer, :destination].include?(opt)
66
+ }
67
+ @raw = false
68
+ end
69
+
70
+ def apply_templates(source)
71
+ transformation_result(:applyTemplates, source)
72
+ end
73
+
74
+ def call_template(template_name)
75
+ transformation_result(:callTemplate, resolve_qname(template_name))
76
+ end
77
+
78
+ private
79
+
80
+ def transformation_result(invocation_method, invocation_arg)
81
+ set_opts!
82
+ transformer_args = [invocation_method, invocation_arg.to_java, destination].compact
83
+ Result.new(result_xdm_value(s9_transformer.send(*transformer_args)), s9_transformer)
84
+ end
85
+
86
+ def result_xdm_value(transformer_return_value)
87
+ XdmValue.wrap_s9_xdm_value(
88
+ transformer_return_value.nil? ? destination.getXdmNode : transformer_return_value
89
+ )
90
+ end
91
+
92
+ def destination
93
+ @destination ||= begin
94
+ Saxon::S9API::XdmDestination.new unless raw?
95
+ end
96
+ end
97
+
98
+ def set_opts!
99
+ opts.each do |opt, value|
100
+ send(opt, value)
101
+ end
102
+ end
103
+
104
+ def raw(value)
105
+ @raw = value
106
+ end
107
+
108
+ def raw?
109
+ @raw
110
+ end
111
+
112
+ def mode(mode_name)
113
+ s9_transformer.setInitialMode(resolve_qname(mode_name).to_java)
114
+ end
115
+
116
+ def resolve_qname(qname)
117
+ case qname
118
+ when Saxon::QName
119
+ qname
120
+ else
121
+ raise Saxon::QName::PrefixedStringWithoutNSURIError if qname.to_s.include?(':')
122
+ Saxon::QName.create(local_name: qname.to_s)
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,69 @@
1
+ require_relative '../qname'
2
+ module Saxon
3
+ module XSLT
4
+ # Represents the static context for an XSLT compiler. {StaticContext}s are immutable.
5
+ class StaticContext
6
+ # methods used by both {StaticContext} and {StaticContext::DSL}
7
+ module Common
8
+ # @param args [Hash]
9
+ # @option args [Hash<String => java.text.Collator>] :declared_collations Hash of URI => Collator bindings
10
+ # @option args [String] :default_collation URI of the default collation
11
+ def initialize(args = {})
12
+ @default_collation = args.fetch(:default_collation, nil).freeze
13
+ end
14
+
15
+ # returns the context details in a hash suitable for initializing a new one
16
+ # @return [Hash<Symbol => Hash,null>] the args hash
17
+ def args_hash
18
+ {
19
+ default_collation: @default_collation
20
+ }
21
+ end
22
+ end
23
+
24
+ # Provides the hooks for constructing a {StaticContext} with a DSL.
25
+ # @api private
26
+ class DSL
27
+ include Common
28
+
29
+ # Create an instance based on the args hash, and execute the passed in Proc/lambda against it using <tt>#instance_exec</tt> and return a
30
+ # new {StaticContext} with the results
31
+ # @param block [Proc] a Proc/lambda (or <tt>to_proc</tt>'d containing DSL calls
32
+ # @return [Saxon::XPath::StaticContext]
33
+ def self.define(block, args = {})
34
+ dsl = new(args)
35
+ dsl.instance_exec(&block) unless block.nil?
36
+ StaticContext.new(dsl.args_hash)
37
+ end
38
+
39
+ # Set the default Collation to use. This should be one of the special
40
+ # collation URIs Saxon recognises, or one that has been registered
41
+ # using Saxon::Processor#declare_collations on the Processor that
42
+ # created the {XSLT::Compiler} this context is for.
43
+ #
44
+ # @param collation_uri [String] The URI of the Collation to set as the default
45
+ def default_collation(collation_uri)
46
+ @default_collation = collation_uri
47
+ end
48
+ end
49
+
50
+ include Common
51
+
52
+ # Executes the Proc/lambda passed in with a new instance of
53
+ # {StaticContext} as <tt>self</tt>, allowing the DSL methods to be
54
+ # called in a DSL-ish way
55
+ #
56
+ # @param block [Proc] the block of DSL calls to be executed
57
+ # @return [Saxon::XSLT::StaticContext] the static context created by the block
58
+ def self.define(block)
59
+ DSL.define(block)
60
+ end
61
+
62
+ attr_reader :default_collation
63
+
64
+ def define(block)
65
+ DSL.define(block, args_hash)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,10 @@
1
+ # this is a generated file, to avoid over-writing it just delete this comment
2
+ begin
3
+ require 'jar_dependencies'
4
+ rescue LoadError
5
+ require 'net/sf/saxon/Saxon-HE/9.9.1-2/Saxon-HE-9.9.1-2.jar'
6
+ end
7
+
8
+ if defined? Jars
9
+ require_jar 'net.sf.saxon', 'Saxon-HE', '9.9.1-2'
10
+ end
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'saxon/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'saxon'
8
+ spec.version = Saxon::VERSION
9
+ spec.authors = ['Matt Patterson']
10
+ spec.email = ['matt@werkstatt.io']
11
+
12
+ spec.description = %q{Wraps the Saxon 9.9 XML and XSLT library so you can process, transform, query, and generate XML documents using XSLT 3, XQuery, and XPath 3.1. The HE open-source version is bundled, but you can use the paid-for PE and EE versions of the Java library with this gem as well.
13
+
14
+ It aims to provide an idiomatic Ruby wrapper around all of Saxon's features.}
15
+ spec.summary = %q{Saxon 9.9 for JRuby, with an idiomatic Ruby API}
16
+ spec.homepage = "https://github.com/fidothe/saxon-rb"
17
+ spec.license = 'MIT'
18
+ spec.platform = 'java'
19
+
20
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
21
+ f.match(%r{^(test|spec|features)/})
22
+ end
23
+ spec.bindir = 'exe'
24
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
+ spec.require_paths = ['lib']
26
+
27
+ spec.requirements << 'jar net.sf.saxon, Saxon-HE, 9.9.1-2'
28
+
29
+ spec.add_development_dependency 'bundler', '~> 2.0'
30
+ spec.add_development_dependency 'jar-dependencies'
31
+ spec.add_development_dependency 'rake', '~> 12.0'
32
+ spec.add_development_dependency 'rspec', '~> 3.0'
33
+ spec.add_development_dependency 'vcr', '~> 4.0'
34
+ spec.add_development_dependency 'addressable', '~> 2.4.0'
35
+ spec.add_development_dependency 'webmock', '~> 2.3.2'
36
+ spec.add_development_dependency 'yard', '~> 0.9.12'
37
+ spec.add_development_dependency 'simplecov', '~> 0.15'
38
+ end
metadata ADDED
@@ -0,0 +1,215 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: saxon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: java
6
+ authors:
7
+ - Matt Patterson
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-04-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.0'
19
+ name: bundler
20
+ prerelease: false
21
+ type: :development
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ name: jar-dependencies
34
+ prerelease: false
35
+ type: :development
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '12.0'
47
+ name: rake
48
+ prerelease: false
49
+ type: :development
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '12.0'
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.0'
61
+ name: rspec
62
+ prerelease: false
63
+ type: :development
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '4.0'
75
+ name: vcr
76
+ prerelease: false
77
+ type: :development
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '4.0'
83
+ - !ruby/object:Gem::Dependency
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 2.4.0
89
+ name: addressable
90
+ prerelease: false
91
+ type: :development
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.4.0
97
+ - !ruby/object:Gem::Dependency
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 2.3.2
103
+ name: webmock
104
+ prerelease: false
105
+ type: :development
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 2.3.2
111
+ - !ruby/object:Gem::Dependency
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: 0.9.12
117
+ name: yard
118
+ prerelease: false
119
+ type: :development
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.9.12
125
+ - !ruby/object:Gem::Dependency
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '0.15'
131
+ name: simplecov
132
+ prerelease: false
133
+ type: :development
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.15'
139
+ description: |-
140
+ Wraps the Saxon 9.9 XML and XSLT library so you can process, transform, query, and generate XML documents using XSLT 3, XQuery, and XPath 3.1. The HE open-source version is bundled, but you can use the paid-for PE and EE versions of the Java library with this gem as well.
141
+
142
+ It aims to provide an idiomatic Ruby wrapper around all of Saxon's features.
143
+ email:
144
+ - matt@werkstatt.io
145
+ executables: []
146
+ extensions: []
147
+ extra_rdoc_files: []
148
+ files:
149
+ - ".gitignore"
150
+ - ".rspec"
151
+ - ".ruby-version"
152
+ - ".travis.yml"
153
+ - CODE_OF_CONDUCT.md
154
+ - Gemfile
155
+ - LICENSE.txt
156
+ - README.md
157
+ - Rakefile
158
+ - bin/console
159
+ - bin/setup
160
+ - lib/net/sf/saxon/Saxon-HE/9.9.1-2/Saxon-HE-9.9.1-2.jar
161
+ - lib/saxon.rb
162
+ - lib/saxon/axis_iterator.rb
163
+ - lib/saxon/configuration.rb
164
+ - lib/saxon/document_builder.rb
165
+ - lib/saxon/item_type.rb
166
+ - lib/saxon/jaxp.rb
167
+ - lib/saxon/loader.rb
168
+ - lib/saxon/occurrence_indicator.rb
169
+ - lib/saxon/parse_options.rb
170
+ - lib/saxon/processor.rb
171
+ - lib/saxon/qname.rb
172
+ - lib/saxon/s9api.rb
173
+ - lib/saxon/serializer.rb
174
+ - lib/saxon/source.rb
175
+ - lib/saxon/version.rb
176
+ - lib/saxon/xdm_atomic_value.rb
177
+ - lib/saxon/xdm_node.rb
178
+ - lib/saxon/xdm_value.rb
179
+ - lib/saxon/xpath.rb
180
+ - lib/saxon/xpath/compiler.rb
181
+ - lib/saxon/xpath/executable.rb
182
+ - lib/saxon/xpath/static_context.rb
183
+ - lib/saxon/xpath/variable_declaration.rb
184
+ - lib/saxon/xslt.rb
185
+ - lib/saxon/xslt/compiler.rb
186
+ - lib/saxon/xslt/executable.rb
187
+ - lib/saxon/xslt/static_context.rb
188
+ - lib/saxon_jars.rb
189
+ - saxon.gemspec
190
+ homepage: https://github.com/fidothe/saxon-rb
191
+ licenses:
192
+ - MIT
193
+ metadata: {}
194
+ post_install_message:
195
+ rdoc_options: []
196
+ require_paths:
197
+ - lib
198
+ required_ruby_version: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ required_rubygems_version: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - ">="
206
+ - !ruby/object:Gem::Version
207
+ version: '0'
208
+ requirements:
209
+ - jar net.sf.saxon, Saxon-HE, 9.9.1-2
210
+ rubyforge_project:
211
+ rubygems_version: 2.7.6
212
+ signing_key:
213
+ specification_version: 4
214
+ summary: Saxon 9.9 for JRuby, with an idiomatic Ruby API
215
+ test_files: []