saxon 0.2.2-java → 0.4.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.
@@ -1,59 +0,0 @@
1
- require_relative '../xdm_node'
2
- require_relative '../xdm_atomic_value'
3
-
4
- module Saxon
5
- module XPath
6
- # Represents a compiled XPath query ready to be executed
7
- class Executable
8
- # @return [XPath::StaticContext] the XPath's static context
9
- attr_reader :static_context
10
-
11
- # @api private
12
- # @param s9_xpath_executable [net.sf.saxon.s9api.XPathExecutable] the
13
- # Saxon compiled XPath object
14
- # @param static_context [XPath::StaticContext] the XPath's static
15
- # context
16
- def initialize(s9_xpath_executable, static_context)
17
- @s9_xpath_executable, @static_context = s9_xpath_executable, static_context
18
- end
19
-
20
- # Run the compiled query using a passed-in node as the context item.
21
- # @param context_item [Saxon::XdmNode] the context item node
22
- # @return [Saxon::XPath::Result] the result of the query as an
23
- # enumerable
24
- def run(context_item, variables = {})
25
- selector = to_java.load
26
- selector.setContextItem(context_item.to_java)
27
- variables.each do |qname_or_string, value|
28
- selector.setVariable(static_context.resolve_variable_qname(qname_or_string).to_java, Saxon::XdmAtomicValue.create(value).to_java)
29
- end
30
- Result.new(selector.iterator)
31
- end
32
-
33
- # @return [net.sf.saxon.s9api.XPathExecutable] the underlying Saxon
34
- # <tt>XPathExecutable</tt>
35
- def to_java
36
- @s9_xpath_executable
37
- end
38
- end
39
-
40
- # The result of executing an XPath query as an enumerable object
41
- class Result
42
- include Enumerable
43
-
44
- # @api private
45
- # @param result_iterator [java.util.Iterator] the result of calling
46
- # <tt>#iterator</tt> on a Saxon <tt>XPathSelector</tt>
47
- def initialize(result_iterator)
48
- @result_iterator = result_iterator
49
- end
50
-
51
- # Yields <tt>XdmNode</tt>s from the query result. If no block is passed,
52
- # returns an <tt>Enumerator</tt>
53
- # @yieldparam xdm_node [Saxon::XdmNode] the name that is yielded
54
- def each(&block)
55
- @result_iterator.lazy.map { |s9_xdm_node| Saxon::XdmNode.new(s9_xdm_node) }.each(&block)
56
- end
57
- end
58
- end
59
- end
@@ -1,161 +0,0 @@
1
- require_relative '../qname'
2
- require_relative './variable_declaration'
3
- module Saxon
4
- module XPath
5
- # Raised when an attempt to declare a variable is made using a string for
6
- # the qname with a namespace prefix that has not been declared in the
7
- # context yet
8
- class MissingVariableNamespaceError < StandardError
9
- def initialize(variable_name, prefix)
10
- @variable_name, @prefix = variable_name, prefix
11
- end
12
-
13
- def to_s
14
- "Namespace prefix ‘#{@prefix}’ for variable name ‘#{@variable_name}’ is not bound to a URI"
15
- end
16
- end
17
-
18
- # Represents the static context for a compiled XPath. {StaticContext}s are immutable.
19
- class StaticContext
20
- # methods used by both {StaticContext} and {StaticContext::DSL}
21
- module Common
22
- # @param args [Hash]
23
- # @option args [Hash<Saxon::QName => Saxon::XPath::VariableDeclaration>] :declared_variables Hash of declared variables
24
- # @option args [Hash<String => String>] :declared_namespaces Hash of namespace bindings prefix => URI
25
- # @option args [Hash<String => java.text.Collator>] :declared_collations Hash of URI => Collator bindings
26
- # @option args [String] :default_collation URI of the default collation
27
- def initialize(args = {})
28
- @declared_variables = args.fetch(:declared_variables, {}).freeze
29
- @declared_namespaces = args.fetch(:declared_namespaces, {}).freeze
30
- @default_collation = args.fetch(:default_collation, nil).freeze
31
- end
32
-
33
- # returns the context details in a hash suitable for initializing a new one
34
- # @return [Hash<Symbol => Hash,null>] the args hash
35
- def args_hash
36
- {
37
- declared_namespaces: @declared_namespaces,
38
- declared_variables: @declared_variables,
39
- default_collation: @default_collation
40
- }
41
- end
42
- end
43
-
44
- # Provides the hooks for constructing a {StaticContext} with a DSL.
45
- # @api private
46
- class DSL
47
- include Common
48
-
49
- # 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
50
- # new {StaticContext} with the results
51
- # @param block [Proc] a Proc/lambda (or <tt>to_proc</tt>'d containing DSL calls
52
- # @return [Saxon::XPath::StaticContext]
53
- def self.define(block, args = {})
54
- dsl = new(args)
55
- dsl.instance_exec(&block) unless block.nil?
56
- StaticContext.new(dsl.args_hash)
57
- end
58
-
59
- # Set the default Collation to use. This should be one of the special
60
- # collation URIs Saxon recognises, or one that has been registered
61
- # using Saxon::Processor#declare_collations on the Processor that
62
- # created the {XPath::Compiler} this context is for.
63
- #
64
- # @param collation_uri [String] The URI of the Collation to set as the default
65
- def default_collation(collation_uri)
66
- @default_collation = collation_uri
67
- end
68
-
69
- # Bind prefixes to namespace URIs
70
- #
71
- # @param namespaces [Hash{String, Symbol => String}]
72
- def namespace(namespaces = {})
73
- @declared_namespaces = @declared_namespaces.merge(namespaces.transform_keys(&:to_s)).freeze
74
- end
75
-
76
- # Declare a XPath variable's existence in the context
77
- #
78
- # @param qname [String, Saxon::QName] The name of the variable as
79
- # explicit QName or prefix:name string form. The string form requires
80
- # the namespace prefix to have already been declared with {#namespace}
81
- # @param type [String, Hash{Symbol => String, Class}, null] The type of the
82
- # variable, either as a string using the same form as an XSLT
83
- # <tt>as=""</tt> type definition, or as a hash of one key/value where
84
- # that key is a Symbol taken from {Saxon::OccurenceIndicator} and the
85
- # value is either a Class that {Saxon::ItemType} can convert to its
86
- # XDM equivalent (e.g. {::String}), or a string that {Saxon::ItemType}
87
- # can parse into an XDM type (e.g. <tt>xs:string</tthat
88
- # {Saxon::ItemType} can parse into an XDM type (e.g.
89
- # <tt>xs:string</tt> or <tt>element()</tt>).
90
- # If it's nil, then the default <tt>item()*</tt> – anything – type declaration is used
91
- def variable(qname, type = nil)
92
- qname = resolve_variable_qname(qname)
93
- @declared_variables = @declared_variables.merge({
94
- qname => resolve_variable_declaration(qname, type)
95
- }).freeze
96
- end
97
-
98
- private
99
-
100
- def resolve_variable_qname(qname_or_string)
101
- Saxon::QName.resolve(qname_or_string, @declared_namespaces)
102
- end
103
-
104
- def resolve_variable_type_decl(type_decl)
105
- case type_decl
106
- when String
107
- occurence_char = type_decl[-1]
108
- occurence = case occurence_char
109
- when '?'
110
- {zero_or_one: type_decl[0..-2]}
111
- when '+'
112
- {one_or_more: type_decl[0..-2]}
113
- when '*'
114
- {zero_or_more: type_decl[0..-2]}
115
- else
116
- {one: type_decl}
117
- end
118
- when Hash
119
- type_decl
120
- end
121
- end
122
-
123
- def resolve_variable_declaration(qname, type)
124
- args_hash = resolve_variable_type_decl(type) || {}
125
- args_hash[:qname] = qname
126
- Saxon::XPath::VariableDeclaration.new(args_hash)
127
- end
128
- end
129
-
130
- include Common
131
-
132
- # Executes the Proc/lambda passed in with a new instance of
133
- # {StaticContext} as <tt>self</tt>, allowing the DSL methods to be
134
- # called in a DSL-ish way
135
- #
136
- # @param block [Proc] the block of DSL calls to be executed
137
- # @return [Saxon::XPath::StaticContext] the static context created by the block
138
- def self.define(block)
139
- DSL.define(block)
140
- end
141
-
142
- attr_reader :declared_variables, :declared_namespaces, :default_collation
143
-
144
- # @return [Saxon::QName]
145
- # @overload resolve_variable_qname(qname)
146
- # returns the QName
147
- # @param qname_or_string [Saxon::QName] the name as a QName
148
- # @overload resolve_variable_qname(string)
149
- # resolve the <tt>prefix:local_name</tt> string into a proper QName by
150
- # looking up the prefix in the {#declared_namespaces}
151
- # @param qname_or_string [String] the name as a string
152
- def resolve_variable_qname(qname_or_string)
153
- Resolver.resolve_variable_qname(qname_or_string, declared_namespaces)
154
- end
155
-
156
- def define(block)
157
- DSL.define(block, args_hash)
158
- end
159
- end
160
- end
161
- end
@@ -1,68 +0,0 @@
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
@@ -1,8 +0,0 @@
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
@@ -1,70 +0,0 @@
1
- require 'forwardable'
2
- require_relative './evaluation_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
- evaluation_context = XSLT::EvaluationContext.define(block)
18
- new(processor.to_java, evaluation_context)
19
- end
20
-
21
- extend Forwardable
22
-
23
- attr_reader :evaluation_context
24
- private :evaluation_context
25
-
26
- # @api private
27
- # @param s9_processor [net.sf.saxon.s9api.Processor] the Saxon
28
- # <tt>Processor</tt> to wrap
29
- # @param evaluation_context [Saxon::XSLT::EvaluationContext] the static context
30
- # XPaths compiled using this compiler will have
31
- def initialize(s9_processor, evaluation_context)
32
- @s9_processor, @evaluation_context = s9_processor, evaluation_context
33
- end
34
-
35
- def_delegators :evaluation_context, :default_collation, :static_parameters, :global_parameters, :initial_template_parameters, :initial_template_tunnel_parameters
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
- # @!attribute [r] static_parameters
41
- # @return [Hash<Saxon::QName => Saxon::XdmValue, Saxon::XdmNode,
42
- # Saxon::XdmAtomicValue>] parameters required at compile time as QName => value hash
43
-
44
- # @param expression [Saxon::Source] the Source to compile
45
- # @return [Saxon::XSLT::Executable] the executable stylesheet
46
- def compile(source, &block)
47
- Saxon::XSLT::Executable.new(
48
- new_compiler.compile(source.to_java),
49
- evaluation_context.define(block)
50
- )
51
- end
52
-
53
- def create(&block)
54
- new_evaluation_context = evaluation_context.define(block)
55
- self.class.new(@s9_processor, new_evaluation_context)
56
- end
57
-
58
- private
59
-
60
- def new_compiler
61
- compiler = @s9_processor.newXsltCompiler
62
- compiler.declareDefaultCollation(default_collation) unless default_collation.nil?
63
- static_parameters.each do |qname, value|
64
- compiler.setParameter(qname.to_java, value.to_java)
65
- end
66
- compiler
67
- end
68
- end
69
- end
70
- end
@@ -1,174 +0,0 @@
1
- require 'set'
2
- require_relative '../qname'
3
-
4
- module Saxon
5
- module XSLT
6
- # Represents the evaluation context for an XSLT compiler, and stylesheets
7
- # compiled using one. {EvaluationContext}s are immutable.
8
- class EvaluationContext
9
- # methods used by both {EvaluationContext} and {EvaluationContext::DSL}
10
- module Common
11
- # @param args [Hash]
12
- # @option args [String] default_collation URI of the default collation
13
- # @option args [Hash<String,Symbol,Saxon::QName =>
14
- # Object,Saxon::XdmValue] static_parameters Hash of QName => value
15
- # bindings for static (compile-time) parameters for this compiler
16
- def initialize(args = {})
17
- @default_collation = args.fetch(:default_collation, nil).freeze
18
- @static_parameters = args.fetch(:static_parameters, {}).freeze
19
- @global_parameters = args.fetch(:global_parameters, {}).freeze
20
- @initial_template_parameters = args.fetch(:initial_template_parameters, {}).freeze
21
- @initial_template_tunnel_parameters = args.fetch(:initial_template_tunnel_parameters, {}).freeze
22
- end
23
-
24
- # returns the context details in a hash suitable for initializing a new one
25
- # @return [Hash<Symbol => Hash,null>] the args hash
26
- def args_hash
27
- check_for_clashing_parameters!
28
- {
29
- default_collation: @default_collation,
30
- static_parameters: @static_parameters,
31
- global_parameters: @global_parameters,
32
- initial_template_parameters: @initial_template_parameters,
33
- initial_template_tunnel_parameters: @initial_template_tunnel_parameters
34
- }
35
- end
36
-
37
- private
38
-
39
- def check_for_clashing_parameters!
40
- @checked ||= begin
41
- if Set.new(@static_parameters.keys).intersect?(Set.new(@global_parameters.keys))
42
- raise GlobalAndStaticParameterClashError
43
- else
44
- true
45
- end
46
- end
47
- end
48
- end
49
-
50
- # Provides the hooks for constructing a {EvaluationContext} with a DSL.
51
- # @api private
52
- class DSL
53
- include Common
54
-
55
- # 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
56
- # new {EvaluationContext} with the results
57
- # @param block [Proc] a Proc/lambda (or <tt>to_proc</tt>'d containing DSL calls
58
- # @return [Saxon::XSLT::EvaluationContext]
59
- def self.define(block, args = {})
60
- dsl = new(args)
61
- dsl.instance_exec(&block) unless block.nil?
62
- EvaluationContext.new(dsl.args_hash)
63
- end
64
-
65
- # Set the default Collation to use. This should be one of the special
66
- # collation URIs Saxon recognises, or one that has been registered
67
- # using Saxon::Processor#declare_collations on the Processor that
68
- # created the {XSLT::Compiler} this context is for.
69
- #
70
- # @param collation_uri [String] The URI of the Collation to set as the default
71
- def default_collation(collation_uri)
72
- @default_collation = collation_uri
73
- end
74
-
75
- # Set the value for static parameters (those that must be known at
76
- # compile-time to avoid an error), as a hash of QName => Value pairs.
77
- # Parameter QNames can be declared as Strings or Symbols if they are
78
- # not in any namespace, otherwise an explicit {Saxon::QName} must be
79
- # used. Values can be provided as explicit XdmValues:
80
- # {Saxon::XdmValue}, {Saxon::XdmNode}, and {Saxon::XdmAtomicValue}, or
81
- # as Ruby objects which will be converted to {Saxon::XdmAtomicValue}s
82
- # in the usual way.
83
- #
84
- # @param parameters [Hash<String,Symbol,Saxon::QName =>
85
- # Object,Saxon::XdmValue>] Hash of QName => value
86
- def static_parameters(parameters = {})
87
- @static_parameters = @static_parameters.merge(process_parameters(parameters)).freeze
88
- end
89
-
90
- # Set the values for global parameters (those that are available to all templates and functions).
91
- #
92
- # @see EvaluationContext#static_parameters for details of the argument format
93
- #
94
- # @param parameters [Hash<String,Symbol,Saxon::QName =>
95
- # Object,Saxon::XdmValue>] Hash of QName => value
96
- def global_parameters(parameters = {})
97
- @global_parameters = @global_parameters.merge(process_parameters(parameters)).freeze
98
- end
99
-
100
- # Set the values for parameters made available only to the initial
101
- # template invoked (either via apply_templates or call_template),
102
- # effectively as if <tt><xsl:with-param tunnel="no"></tt> was being used.
103
- #
104
- # @see EvaluationContext#static_parameters for details of the argument format
105
- #
106
- # @param parameters [Hash<String,Symbol,Saxon::QName =>
107
- # Object,Saxon::XdmValue>] Hash of QName => value
108
- def initial_template_parameters(parameters = {})
109
- @initial_template_parameters = @initial_template_parameters.merge(process_parameters(parameters))
110
- end
111
-
112
- # Set the values for tunneling parameters made available only to the initial
113
- # template invoked (either via apply_templates or call_template),
114
- # effectively as if <tt><xsl:with-param tunnel="yes"></tt> was being used.
115
- #
116
- # @see EvaluationContext#static_parameters for details of the argument format
117
- #
118
- # @param parameters [Hash<String,Symbol,Saxon::QName =>
119
- # Object,Saxon::XdmValue>] Hash of QName => value
120
- def initial_template_tunnel_parameters(parameters = {})
121
- @initial_template_tunnel_parameters = @initial_template_tunnel_parameters.merge(process_parameters(parameters))
122
- end
123
-
124
- private
125
-
126
- def process_parameters(parameters)
127
- XSLT::ParameterHelper.process_parameters(parameters)
128
- end
129
- end
130
-
131
- include Common
132
-
133
- # Executes the Proc/lambda passed in with a new instance of
134
- # {EvaluationContext} as <tt>self</tt>, allowing the DSL methods to be
135
- # called in a DSL-ish way
136
- #
137
- # @param block [Proc] the block of DSL calls to be executed
138
- # @return [Saxon::XSLT::EvaluationContext] the static context created by the block
139
- def self.define(block)
140
- DSL.define(block)
141
- end
142
-
143
- attr_reader :default_collation, :static_parameters, :global_parameters, :initial_template_parameters, :initial_template_tunnel_parameters
144
-
145
- def define(block)
146
- block.nil? ? self : DSL.define(block, args_hash)
147
- end
148
- end
149
-
150
- class GlobalAndStaticParameterClashError < StandardError
151
- end
152
-
153
- module ParameterHelper
154
- def self.process_parameters(parameters)
155
- Hash[parameters.map { |qname, value|
156
- [Saxon::QName.resolve(qname), process_xdm_value(value)]
157
- }]
158
- end
159
-
160
- def self.process_xdm_value(value)
161
- case value
162
- when Saxon::XdmValue, Saxon::XdmNode, Saxon::XdmAtomicValue
163
- value
164
- else
165
- Saxon::XdmAtomicValue.create(value)
166
- end
167
- end
168
-
169
- def self.to_java(parameters)
170
- Hash[parameters.map { |k,v| [k.to_java, v.to_java] }].to_java
171
- end
172
- end
173
- end
174
- end