saxon 0.2.2-java → 0.4.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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