saxon-rb 0.4.0-java → 0.7.2-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 +4 -4
- data/.circleci/config.yml +429 -42
- data/.ruby-version +1 -1
- data/.yardopts +1 -0
- data/Gemfile +2 -2
- data/README.md +358 -10
- data/Rakefile +237 -7
- data/docs/templates/plugin.rb +73 -0
- data/lib/net/sf/saxon/Saxon-HE/{9.9.1-5/Saxon-HE-9.9.1-5.jar → 9.9.1-6/Saxon-HE-9.9.1-6.jar} +0 -0
- data/lib/saxon-rb.rb +0 -0
- data/lib/{saxon_jars.rb → saxon-rb_jars.rb} +2 -2
- data/lib/saxon.rb +13 -0
- data/lib/saxon/axis_iterator.rb +8 -1
- data/lib/saxon/configuration.rb +16 -13
- data/lib/saxon/document_builder.rb +216 -5
- data/lib/saxon/feature_flags.rb +11 -0
- data/lib/saxon/feature_flags/errors.rb +8 -0
- data/lib/saxon/feature_flags/helpers.rb +15 -0
- data/lib/saxon/feature_flags/version.rb +100 -0
- data/lib/saxon/item_type.rb +129 -89
- data/lib/saxon/item_type/lexical_string_conversion.rb +214 -59
- data/lib/saxon/item_type/value_to_ruby.rb +25 -0
- data/lib/saxon/loader.rb +6 -1
- data/lib/saxon/nokogiri.rb +78 -0
- data/lib/saxon/occurrence_indicator.rb +32 -3
- data/lib/saxon/processor.rb +50 -5
- data/lib/saxon/qname.rb +37 -2
- data/lib/saxon/s9api.rb +5 -0
- data/lib/saxon/sequence_type.rb +131 -0
- data/lib/saxon/serializer.rb +3 -137
- data/lib/saxon/serializer/destination.rb +80 -0
- data/lib/saxon/serializer/object.rb +93 -0
- data/lib/saxon/serializer/output_properties.rb +83 -0
- data/lib/saxon/source.rb +207 -71
- data/lib/saxon/version.rb +7 -1
- data/lib/saxon/version/library.rb +89 -0
- data/lib/saxon/xdm.rb +7 -0
- data/lib/saxon/xdm/array.rb +16 -0
- data/lib/saxon/xdm/atomic_value.rb +10 -2
- data/lib/saxon/xdm/empty_sequence.rb +13 -0
- data/lib/saxon/xdm/external_object.rb +1 -0
- data/lib/saxon/xdm/function_item.rb +1 -0
- data/lib/saxon/xdm/item.rb +7 -0
- data/lib/saxon/xdm/map.rb +38 -0
- data/lib/saxon/xdm/node.rb +50 -1
- data/lib/saxon/xdm/sequence_like.rb +15 -0
- data/lib/saxon/xdm/value.rb +21 -5
- data/lib/saxon/xpath.rb +9 -0
- data/lib/saxon/xpath/compiler.rb +37 -2
- data/lib/saxon/xpath/executable.rb +53 -28
- data/lib/saxon/xpath/static_context.rb +25 -40
- data/lib/saxon/xpath/variable_declaration.rb +16 -49
- data/lib/saxon/xslt.rb +12 -0
- data/lib/saxon/xslt/compiler.rb +75 -6
- data/lib/saxon/xslt/evaluation_context.rb +30 -4
- data/lib/saxon/xslt/executable.rb +206 -29
- data/lib/saxon/xslt/invocation.rb +97 -0
- data/saxon-rb.gemspec +3 -3
- metadata +22 -10
- data/saxon.gemspec +0 -30
data/lib/saxon/xpath.rb
CHANGED
@@ -3,6 +3,15 @@ require_relative './xpath/compiler'
|
|
3
3
|
module Saxon
|
4
4
|
# Classes for compiling, configuring, and executing XPath queries against
|
5
5
|
# XDM nodes or documents
|
6
|
+
#
|
7
|
+
# Using an XPath involves creating a compiler, compiling an XPath into an
|
8
|
+
# executable, and then running that XPath executable against an XDM node.
|
9
|
+
#
|
10
|
+
# The easiest way to create an XPath::Compiler instance is by using the {Saxon::Processor#xpath_compiler} method.
|
11
|
+
#
|
12
|
+
# @see Saxon::XPath::Compiler
|
13
|
+
# @see Saxon::XPath::Executable
|
14
|
+
# @see Saxon::Processor#xpath_compiler
|
6
15
|
module XPath
|
7
16
|
end
|
8
17
|
end
|
data/lib/saxon/xpath/compiler.rb
CHANGED
@@ -4,14 +4,43 @@ require_relative './executable'
|
|
4
4
|
|
5
5
|
module Saxon
|
6
6
|
module XPath
|
7
|
-
#
|
7
|
+
# An {XPath::Compiler} turns XPath expressions into executable queries you
|
8
|
+
# can run against XDM Nodes (like XML documents, or parts of XML documents).
|
9
|
+
#
|
10
|
+
# To compile an XPath requires an +XPath::Compiler+ instance. You can create
|
11
|
+
# one by calling {Compiler.create} and passing a {Saxon::Processor}, with an
|
12
|
+
# optional block for context like bound namespaces and declared variables.
|
13
|
+
# Alternately, and much more easily, you can call {Processor#xpath_compiler}
|
14
|
+
# on the {Saxon::Processor} instance you're already working with.
|
15
|
+
#
|
16
|
+
# processor = Saxon::Processor.create
|
17
|
+
# compiler = processor.xpath_compiler {
|
18
|
+
# namespace a: 'http://example.org/a'
|
19
|
+
# variable 'a:var', 'xs:string'
|
20
|
+
# }
|
21
|
+
# # Or...
|
22
|
+
# compiler = Saxon::XPath::Compiler.create(processor) {
|
23
|
+
# namespace a: 'http://example.org/a'
|
24
|
+
# variable 'a:var', 'xs:string'
|
25
|
+
# }
|
26
|
+
# xpath = compiler.compile('//a:element[@attr = $a:var]')
|
27
|
+
# matches = xpath.evaluate(document_node, {
|
28
|
+
# 'a:var' => 'the value'
|
29
|
+
# }) #=> Saxon::XDM::Value
|
30
|
+
#
|
31
|
+
# In order to use prefixed QNames in your XPaths, like +/ns:name/+, then you need
|
32
|
+
# to declare prefix/namespace URI bindings when you create a compiler.
|
33
|
+
#
|
34
|
+
# It's also possible to make use of variables in your XPaths by declaring them at
|
35
|
+
# the compiler creation stage, and then passing in values for them as XPath run
|
36
|
+
# time.
|
8
37
|
class Compiler
|
9
38
|
# Create a new <tt>XPath::Compiler</tt> using the supplied Processor.
|
10
39
|
# Passing a block gives access to a DSL for setting up the compiler's
|
11
40
|
# static context.
|
12
41
|
#
|
13
42
|
# @param processor [Saxon::Processor] the {Saxon::Processor} to use
|
14
|
-
# @yield An XPath
|
43
|
+
# @yield An XPath::StaticContext::DSL block
|
15
44
|
# @return [Saxon::XPath::Compiler] the new compiler instance
|
16
45
|
def self.create(processor, &block)
|
17
46
|
static_context = XPath::StaticContext.define(block)
|
@@ -46,6 +75,12 @@ module Saxon
|
|
46
75
|
Saxon::XPath::Executable.new(new_compiler.compile(expression), static_context)
|
47
76
|
end
|
48
77
|
|
78
|
+
# Allows the creation of a new {Compiler} starting from a copy of this
|
79
|
+
# Compiler's static context. As with {.create}, passing a block gives
|
80
|
+
# access to a DSL for setting up the compiler's static context.
|
81
|
+
#
|
82
|
+
# @yield An XPath::StaticContext::DSL block
|
83
|
+
# @return [Saxon::XPath::Compiler] the new compiler instance
|
49
84
|
def create(&block)
|
50
85
|
new_static_context = static_context.define(block)
|
51
86
|
self.class.new(@s9_processor, new_static_context)
|
@@ -2,7 +2,23 @@ require_relative '../xdm'
|
|
2
2
|
|
3
3
|
module Saxon
|
4
4
|
module XPath
|
5
|
-
# Represents a compiled XPath query ready to be executed
|
5
|
+
# Represents a compiled XPath query ready to be executed. An
|
6
|
+
# {XPath::Executable} is created by compiling an XPath expression with
|
7
|
+
# {XPath::Compiler#compile}.
|
8
|
+
#
|
9
|
+
# To run the +XPath::Executable+ you can call {XPath::Executable#evaluate},
|
10
|
+
# to generate an {XDM::Value} of the results, or you can call
|
11
|
+
# {XPath::Executable#as_enum} to return an Enumerator over the results.
|
12
|
+
#
|
13
|
+
# processor = Saxon::Processor.create
|
14
|
+
# compiler = processor.xpath_compiler
|
15
|
+
# xpath = compiler.compile('//element[@attr = $var]')
|
16
|
+
#
|
17
|
+
# matches = xpath.evaluate(document_node, {'var' => 'the value'}) #=> Saxon::XDM::Value
|
18
|
+
#
|
19
|
+
# xpath.as_enum(document_node, {'var' => 'the value'}).each do |node|
|
20
|
+
# ...
|
21
|
+
# end
|
6
22
|
class Executable
|
7
23
|
# @return [XPath::StaticContext] the XPath's static context
|
8
24
|
attr_reader :static_context
|
@@ -16,17 +32,34 @@ module Saxon
|
|
16
32
|
@s9_xpath_executable, @static_context = s9_xpath_executable, static_context
|
17
33
|
end
|
18
34
|
|
19
|
-
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
35
|
+
|
36
|
+
# Evaluate the XPath against the context node given and return an
|
37
|
+
# +Enumerator+ over the result.
|
38
|
+
#
|
39
|
+
# @param context_item [Saxon::XDM::Node, Saxon::XDM::AtomicValue] the item
|
40
|
+
# to be used as the context item for evaluating the XPath from.
|
41
|
+
# @param variables [Hash<Saxon::QName => Saxon::XDM::Value, Saxon::XDM::Node,
|
42
|
+
# Saxon::XDM::AtomicValue>] any variable values to set within the XPath
|
43
|
+
# @return [Enumerator] an Enumerator over the items in the result sequence
|
44
|
+
def as_enum(context_item, variables = {})
|
45
|
+
generate_selector(context_item, variables).iterator.lazy.
|
46
|
+
map { |s9_xdm_object| Saxon::XDM.Value(s9_xdm_object) }
|
47
|
+
end
|
48
|
+
|
49
|
+
# Evaluate the XPath against the context node given and return the result.
|
50
|
+
#
|
51
|
+
# If the result is a single item, then that will be returned directly
|
52
|
+
# (e.g. an {XDM::Node} or an {XDM::AtomicValue}). If the result is an
|
53
|
+
# empty sequence then {XDM::EmptySequence} is returned.
|
54
|
+
#
|
55
|
+
# @param context_item [Saxon::XDM::Node, Saxon::XDM::AtomicValue] the item
|
56
|
+
# to be used as the context item for evaluating the XPath from.
|
57
|
+
# @param variables [Hash<Saxon::QName => Saxon::XDM::Value, Saxon::XDM::Node,
|
58
|
+
# Saxon::XDM::AtomicValue>] any variable values to set within the XPath
|
59
|
+
# @return [Saxon::XDM::Value] the XDM value returned
|
60
|
+
def evaluate(context_item, variables = {})
|
61
|
+
s9_xdm_value = generate_selector(context_item, variables).evaluate
|
62
|
+
Saxon::XDM.Value(s9_xdm_value)
|
30
63
|
end
|
31
64
|
|
32
65
|
# @return [net.sf.saxon.s9api.XPathExecutable] the underlying Saxon
|
@@ -34,24 +67,16 @@ module Saxon
|
|
34
67
|
def to_java
|
35
68
|
@s9_xpath_executable
|
36
69
|
end
|
37
|
-
end
|
38
70
|
|
39
|
-
|
40
|
-
class Result
|
41
|
-
include Enumerable
|
71
|
+
private
|
42
72
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
# Yields <tt>XDM::Node</tt>s from the query result. If no block is passed,
|
51
|
-
# returns an <tt>Enumerator</tt>
|
52
|
-
# @yieldparam xdm_node [Saxon::XDM::Node] the name that is yielded
|
53
|
-
def each(&block)
|
54
|
-
@result_iterator.lazy.map { |s9_xdm_node| Saxon::XDM::Node.new(s9_xdm_node) }.each(&block)
|
73
|
+
def generate_selector(context_item, variables = {})
|
74
|
+
selector = to_java.load
|
75
|
+
selector.setContextItem(context_item.to_java)
|
76
|
+
variables.each do |qname_or_string, value|
|
77
|
+
selector.setVariable(static_context.resolve_variable_qname(qname_or_string).to_java, Saxon::XDM.Value(value).to_java)
|
78
|
+
end
|
79
|
+
selector
|
55
80
|
end
|
56
81
|
end
|
57
82
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require_relative '../qname'
|
2
2
|
require_relative './variable_declaration'
|
3
|
+
|
3
4
|
module Saxon
|
4
5
|
module XPath
|
5
6
|
# Raised when an attempt to declare a variable is made using a string for
|
@@ -10,11 +11,13 @@ module Saxon
|
|
10
11
|
@variable_name, @prefix = variable_name, prefix
|
11
12
|
end
|
12
13
|
|
14
|
+
# error message reports which unbound prefix is a problem, and how it was used
|
13
15
|
def to_s
|
14
16
|
"Namespace prefix ‘#{@prefix}’ for variable name ‘#{@variable_name}’ is not bound to a URI"
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
20
|
+
# @api private
|
18
21
|
# Represents the static context for a compiled XPath. {StaticContext}s are immutable.
|
19
22
|
class StaticContext
|
20
23
|
# methods used by both {StaticContext} and {StaticContext::DSL}
|
@@ -41,11 +44,12 @@ module Saxon
|
|
41
44
|
end
|
42
45
|
end
|
43
46
|
|
47
|
+
# @api public
|
44
48
|
# Provides the hooks for constructing a {StaticContext} with a DSL.
|
45
|
-
# @api private
|
46
49
|
class DSL
|
47
50
|
include Common
|
48
51
|
|
52
|
+
# @api private
|
49
53
|
# 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
54
|
# new {StaticContext} with the results
|
51
55
|
# @param block [Proc] a Proc/lambda (or <tt>to_proc</tt>'d containing DSL calls
|
@@ -70,28 +74,23 @@ module Saxon
|
|
70
74
|
#
|
71
75
|
# @param namespaces [Hash{String, Symbol => String}]
|
72
76
|
def namespace(namespaces = {})
|
73
|
-
@declared_namespaces = @declared_namespaces.merge(namespaces.
|
77
|
+
@declared_namespaces = @declared_namespaces.merge(namespaces.map { |k, v| [k.to_s, v] }.to_h).freeze
|
74
78
|
end
|
75
79
|
|
76
80
|
# Declare a XPath variable's existence in the context
|
77
81
|
#
|
78
82
|
# @param qname [String, Saxon::QName] The name of the variable as
|
79
|
-
#
|
80
|
-
#
|
81
|
-
# @param
|
82
|
-
# variable, either as a string using the same form as an XSLT
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
|
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)
|
83
|
+
# explicit QName or prefix:name string form. The string form requires
|
84
|
+
# the namespace prefix to have already been declared with {#namespace}
|
85
|
+
# @param sequence_type [String, Saxon::SequenceType, null] The type of
|
86
|
+
# the variable, either as a string using the same form as an XSLT
|
87
|
+
# <tt>as=""</tt> type definition, or as a {Saxon::SequenceType} directly.
|
88
|
+
#
|
89
|
+
# If it's nil, then the default <tt>item()*</tt> – anything – type declaration is used
|
90
|
+
def variable(qname, sequence_type = nil)
|
92
91
|
qname = resolve_variable_qname(qname)
|
93
92
|
@declared_variables = @declared_variables.merge({
|
94
|
-
qname => resolve_variable_declaration(qname,
|
93
|
+
qname => resolve_variable_declaration(qname, sequence_type)
|
95
94
|
}).freeze
|
96
95
|
end
|
97
96
|
|
@@ -101,29 +100,8 @@ module Saxon
|
|
101
100
|
Saxon::QName.resolve(qname_or_string, @declared_namespaces)
|
102
101
|
end
|
103
102
|
|
104
|
-
def
|
105
|
-
|
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)
|
103
|
+
def resolve_variable_declaration(qname, sequence_type = nil)
|
104
|
+
Saxon::XPath::VariableDeclaration.new(qname, Saxon.SequenceType(sequence_type || 'item()*'))
|
127
105
|
end
|
128
106
|
end
|
129
107
|
|
@@ -139,7 +117,12 @@ module Saxon
|
|
139
117
|
DSL.define(block)
|
140
118
|
end
|
141
119
|
|
142
|
-
|
120
|
+
# @return [String] The default collation URI as a String
|
121
|
+
attr_reader :default_collation
|
122
|
+
# @return [Hash<Saxon::QName => Saxon::XPath::VariableDeclaration] the declared variables
|
123
|
+
attr_reader :declared_variables
|
124
|
+
# @return [Hash<String => String>] the declared namespaces, as a prefix => uri hash
|
125
|
+
attr_reader :declared_namespaces
|
143
126
|
|
144
127
|
# @return [Saxon::QName]
|
145
128
|
# @overload resolve_variable_qname(qname)
|
@@ -153,6 +136,8 @@ module Saxon
|
|
153
136
|
Saxon::QName.resolve(qname_or_string, declared_namespaces)
|
154
137
|
end
|
155
138
|
|
139
|
+
# @api private
|
140
|
+
# Create a new {StaticContext} based on this one. Passed Proc is evaluated in the same way as {DSL.define}
|
156
141
|
def define(block)
|
157
142
|
DSL.define(block, args_hash)
|
158
143
|
end
|
@@ -1,67 +1,34 @@
|
|
1
|
-
require_relative '../
|
2
|
-
require_relative '../occurrence_indicator'
|
1
|
+
require_relative '../sequence_type'
|
3
2
|
|
4
3
|
module Saxon
|
5
4
|
module XPath
|
6
|
-
# Represents an XPath variable declaration in the static context of a
|
5
|
+
# Represents an XPath variable declaration in the static context of a
|
6
|
+
# compiled XPath, providing an idiomatic Ruby way to deal with these.
|
7
7
|
class VariableDeclaration
|
8
8
|
# @return [Saxon::QName]
|
9
9
|
attr_reader :qname
|
10
|
-
# @return [Saxon::
|
11
|
-
attr_reader :
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
@qname = opts.fetch(:qname)
|
20
|
-
@item_type, @occurrences = extract_type_decl(opts.reject { |k, v| k == :qname })
|
10
|
+
# @return [Saxon::SequenceType]
|
11
|
+
attr_reader :sequence_type
|
12
|
+
|
13
|
+
# @param qname [Saxon::QName] the name of the variable
|
14
|
+
# @param sequence_type [Saxon::SequenceType] the SequenceType of the
|
15
|
+
# variable
|
16
|
+
def initialize(qname, sequence_type)
|
17
|
+
@qname = qname
|
18
|
+
@sequence_type = sequence_type || Saxon.SequenceType('item()*')
|
21
19
|
end
|
22
20
|
|
23
|
-
# VariableDeclarations compare equal if their qname
|
21
|
+
# VariableDeclarations compare equal if their qname and sequence_type are equal
|
24
22
|
# @param other [Saxon::VariableDeclaration]
|
25
23
|
# @return [Boolean]
|
26
24
|
def ==(other)
|
27
|
-
VariableDeclaration === other && qname == other.qname &&
|
25
|
+
VariableDeclaration === other && qname == other.qname && sequence_type == other.sequence_type
|
28
26
|
end
|
29
27
|
|
30
28
|
# @api private
|
29
|
+
# return the arguments XPathCompiler.declareVariable expects
|
31
30
|
def compiler_args
|
32
|
-
[qname.to_java, item_type.to_java,
|
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(', ')}"
|
31
|
+
[qname.to_java, sequence_type.item_type.to_java, sequence_type.occurrence_indicator.to_java]
|
65
32
|
end
|
66
33
|
end
|
67
34
|
end
|
data/lib/saxon/xslt.rb
CHANGED
@@ -3,6 +3,18 @@ require_relative './xslt/compiler'
|
|
3
3
|
module Saxon
|
4
4
|
# Classes for compiling, configuring, and executing XSLT transformations
|
5
5
|
# against XDM nodes or documents
|
6
|
+
#
|
7
|
+
# Using XSLT involves creating a compiler, compiling an XSLT file into an
|
8
|
+
# executable, and then invoking that executable through applying templates
|
9
|
+
# against an XML document, calling a named template, or calling a named
|
10
|
+
# function.
|
11
|
+
#
|
12
|
+
# The easiest way to create an {XSLT::Compiler} instance is by using the
|
13
|
+
# {Saxon::Processor#xslt_compiler} method.
|
14
|
+
#
|
15
|
+
# @see Saxon::XSLT::Compiler
|
16
|
+
# @see Saxon::XSLT::Executable
|
17
|
+
# @see Saxon::Processor#xslt_compiler
|
6
18
|
module XSLT
|
7
19
|
end
|
8
20
|
end
|
data/lib/saxon/xslt/compiler.rb
CHANGED
@@ -4,7 +4,67 @@ require_relative './executable'
|
|
4
4
|
|
5
5
|
module Saxon
|
6
6
|
module XSLT
|
7
|
-
#
|
7
|
+
# The simplest way to construct an {XSLT::Compiler} is to call
|
8
|
+
# {Saxon::Processor#xslt_compiler}.
|
9
|
+
#
|
10
|
+
# processor = Saxon::Processor.create
|
11
|
+
# # Simplest, default options
|
12
|
+
# compiler = processor.xslt_compiler
|
13
|
+
#
|
14
|
+
# In order to set compile-time options, declare static compile-time
|
15
|
+
# parameters then pass a block to the method using the DSL syntax (see
|
16
|
+
# {Saxon::XSLT::EvaluationContext::DSL}
|
17
|
+
#
|
18
|
+
# compiler = processor.xslt_compiler {
|
19
|
+
# static_parameters 'param' => 'value'
|
20
|
+
# default_collation 'https://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive/'
|
21
|
+
# }
|
22
|
+
#
|
23
|
+
# The static evaluation context for a Compiler cannot be changed, you must
|
24
|
+
# create a new one with the context you want. It’s very simple to create a
|
25
|
+
# new Compiler based on an existing one. Declaring a parameter with a an
|
26
|
+
# existing name overwrites the old value.
|
27
|
+
#
|
28
|
+
# new_compiler = compiler.create {
|
29
|
+
# static_parameters 'param' => 'new value'
|
30
|
+
# }
|
31
|
+
# new_compiler.default_collation #=> "https://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive/"
|
32
|
+
#
|
33
|
+
# If you wanted to remove a value, you need to start from scratch. You can,
|
34
|
+
# of course, extract any data you want from a compiler instance separately
|
35
|
+
# and use that to create a new one.
|
36
|
+
#
|
37
|
+
# params = compiler.static_parameters
|
38
|
+
# new_compiler = processor.xslt_compiler {
|
39
|
+
# static_parameters params
|
40
|
+
# }
|
41
|
+
# new_compiler.default_collation #=> nil
|
42
|
+
#
|
43
|
+
# Once you have a compiler, call {Compiler#compile} and pass in a
|
44
|
+
# {Saxon::Source} or an existing {Saxon::XDM::Node}. Parameters and other
|
45
|
+
# run-time configuration options can be set using a block in the same way as
|
46
|
+
# creating a compiler. You'll be returned a {Saxon::XSLT::Executable}.
|
47
|
+
#
|
48
|
+
# source = Saxon::Source.create('my.xsl')
|
49
|
+
# xslt = compiler.compile(source) {
|
50
|
+
# initial_template_parameters 'param' => 'other value'
|
51
|
+
# }
|
52
|
+
#
|
53
|
+
# You can also pass in (or override) parameters at stylesheet execution
|
54
|
+
# time, but if you'll be executing the same stylesheet against many
|
55
|
+
# documents with the same initial parameters then setting them at compile
|
56
|
+
# time is simpler.
|
57
|
+
#
|
58
|
+
# Global and initial template parameters can be set at compiler creation
|
59
|
+
# time, compile time, or execution time. Static parameters can only be set
|
60
|
+
# at compiler creation or compile time.
|
61
|
+
#
|
62
|
+
# xslt = compiler.compile(source) {
|
63
|
+
# static_parameters 'static-param' => 'static value'
|
64
|
+
# global_parameters 'param' => 'global value'
|
65
|
+
# initial_template_parameters 'param' => 'other value'
|
66
|
+
# initial_template_tunnel_parameters 'param' => 'tunnel value'
|
67
|
+
# }
|
8
68
|
class Compiler
|
9
69
|
# Create a new <tt>XSLT::Compiler</tt> using the supplied Processor.
|
10
70
|
# Passing a block gives access to a DSL for setting up the compiler's
|
@@ -42,14 +102,23 @@ module Saxon
|
|
42
102
|
# Saxon::XDM::AtomicValue>] parameters required at compile time as QName => value hash
|
43
103
|
|
44
104
|
# @param source [Saxon::Source] the Source to compile
|
105
|
+
# @yield the block is executed in the context of an {XSLT::EvaluationContext} DSL instance
|
45
106
|
# @return [Saxon::XSLT::Executable] the executable stylesheet
|
46
107
|
def compile(source, &block)
|
108
|
+
new_evaluation_context = evaluation_context.define(block)
|
109
|
+
s9_compiler = new_compiler(new_evaluation_context)
|
47
110
|
Saxon::XSLT::Executable.new(
|
48
|
-
|
49
|
-
|
111
|
+
s9_compiler.compile(source.to_java),
|
112
|
+
new_evaluation_context
|
50
113
|
)
|
51
114
|
end
|
52
115
|
|
116
|
+
# Allows the creation of a new {Compiler} starting from a copy of this
|
117
|
+
# Compiler's static context. As with {.create}, passing a block gives
|
118
|
+
# access to a DSL for setting up the compiler's static context.
|
119
|
+
#
|
120
|
+
# @yield An XSLT compiler DSL block
|
121
|
+
# @return [Saxon::XSLT::Compiler] the new compiler instance
|
53
122
|
def create(&block)
|
54
123
|
new_evaluation_context = evaluation_context.define(block)
|
55
124
|
self.class.new(@s9_processor, new_evaluation_context)
|
@@ -57,10 +126,10 @@ module Saxon
|
|
57
126
|
|
58
127
|
private
|
59
128
|
|
60
|
-
def new_compiler
|
129
|
+
def new_compiler(evaluation_context)
|
61
130
|
compiler = @s9_processor.newXsltCompiler
|
62
|
-
compiler.declareDefaultCollation(default_collation) unless default_collation.nil?
|
63
|
-
static_parameters.each do |qname, value|
|
131
|
+
compiler.declareDefaultCollation(evaluation_context.default_collation) unless evaluation_context.default_collation.nil?
|
132
|
+
evaluation_context.static_parameters.each do |qname, value|
|
64
133
|
compiler.setParameter(qname.to_java, value.to_java)
|
65
134
|
end
|
66
135
|
compiler
|