saxon-rb 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.
- checksums.yaml +7 -0
- data/.circleci/config.yml +62 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +20 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/net/sf/saxon/Saxon-HE/9.9.1-5/Saxon-HE-9.9.1-5.jar +0 -0
- data/lib/saxon.rb +6 -0
- data/lib/saxon/axis_iterator.rb +31 -0
- data/lib/saxon/configuration.rb +116 -0
- data/lib/saxon/document_builder.rb +28 -0
- data/lib/saxon/item_type.rb +290 -0
- data/lib/saxon/item_type/lexical_string_conversion.rb +383 -0
- data/lib/saxon/item_type/value_to_ruby.rb +78 -0
- data/lib/saxon/jaxp.rb +8 -0
- data/lib/saxon/loader.rb +93 -0
- data/lib/saxon/occurrence_indicator.rb +33 -0
- data/lib/saxon/parse_options.rb +127 -0
- data/lib/saxon/processor.rb +102 -0
- data/lib/saxon/qname.rb +153 -0
- data/lib/saxon/s9api.rb +34 -0
- data/lib/saxon/serializer.rb +143 -0
- data/lib/saxon/source.rb +187 -0
- data/lib/saxon/version.rb +3 -0
- data/lib/saxon/xdm.rb +35 -0
- data/lib/saxon/xdm/array.rb +77 -0
- data/lib/saxon/xdm/atomic_value.rb +173 -0
- data/lib/saxon/xdm/empty_sequence.rb +37 -0
- data/lib/saxon/xdm/external_object.rb +21 -0
- data/lib/saxon/xdm/function_item.rb +21 -0
- data/lib/saxon/xdm/item.rb +32 -0
- data/lib/saxon/xdm/map.rb +77 -0
- data/lib/saxon/xdm/node.rb +71 -0
- data/lib/saxon/xdm/sequence_like.rb +30 -0
- data/lib/saxon/xdm/value.rb +145 -0
- data/lib/saxon/xpath.rb +8 -0
- data/lib/saxon/xpath/compiler.rb +69 -0
- data/lib/saxon/xpath/executable.rb +58 -0
- data/lib/saxon/xpath/static_context.rb +161 -0
- data/lib/saxon/xpath/variable_declaration.rb +68 -0
- data/lib/saxon/xslt.rb +8 -0
- data/lib/saxon/xslt/compiler.rb +70 -0
- data/lib/saxon/xslt/evaluation_context.rb +165 -0
- data/lib/saxon/xslt/executable.rb +156 -0
- data/lib/saxon_jars.rb +10 -0
- data/saxon-rb.gemspec +39 -0
- data/saxon.gemspec +30 -0
- metadata +240 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative '../axis_iterator'
|
2
|
+
require_relative '../s9api'
|
3
|
+
require_relative 'sequence_like'
|
4
|
+
|
5
|
+
module Saxon
|
6
|
+
module XDM
|
7
|
+
# An XPath Data Model Node object, representing an XML document, or an element or one of the other node chunks in the XDM.
|
8
|
+
class Node
|
9
|
+
include XDM::SequenceLike
|
10
|
+
include XDM::ItemSequenceLike
|
11
|
+
include Enumerable
|
12
|
+
|
13
|
+
attr_reader :s9_xdm_node
|
14
|
+
private :s9_xdm_node
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
def initialize(s9_xdm_node)
|
18
|
+
@s9_xdm_node = s9_xdm_node
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Saxon::S9API::XdmNode] The underlying Saxon Java XDM node object.
|
22
|
+
def to_java
|
23
|
+
@s9_xdm_node
|
24
|
+
end
|
25
|
+
|
26
|
+
def node_name
|
27
|
+
return @node_name if instance_variable_defined?(:@node_name)
|
28
|
+
node_name = s9_xdm_node.getNodeName
|
29
|
+
@node_name = node_name.nil? ? nil : Saxon::QName.new(node_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def node_kind
|
33
|
+
@node_kind ||= case s9_xdm_node.nodeKind
|
34
|
+
when Saxon::S9API::XdmNodeKind::ELEMENT
|
35
|
+
:element
|
36
|
+
when Saxon::S9API::XdmNodeKind::TEXT
|
37
|
+
:text
|
38
|
+
when Saxon::S9API::XdmNodeKind::ATTRIBUTE
|
39
|
+
:attribute
|
40
|
+
when Saxon::S9API::XdmNodeKind::NAMESPACE
|
41
|
+
:namespace
|
42
|
+
when Saxon::S9API::XdmNodeKind::COMMENT
|
43
|
+
:comment
|
44
|
+
when Saxon::S9API::XdmNodeKind::PROCESSING_INSTRUCTION
|
45
|
+
:processing_instruction
|
46
|
+
when Saxon::S9API::XdmNodeKind::DOCUMENT
|
47
|
+
:document
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def ==(other)
|
52
|
+
return false unless other.is_a?(XDM::Node)
|
53
|
+
s9_xdm_node.equals(other.to_java)
|
54
|
+
end
|
55
|
+
|
56
|
+
alias_method :eql?, :==
|
57
|
+
|
58
|
+
def hash
|
59
|
+
@hash ||= s9_xdm_node.hashCode
|
60
|
+
end
|
61
|
+
|
62
|
+
def each(&block)
|
63
|
+
axis_iterator(:child).each(&block)
|
64
|
+
end
|
65
|
+
|
66
|
+
def axis_iterator(axis)
|
67
|
+
AxisIterator.new(self, axis)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Saxon
|
2
|
+
module XDM
|
3
|
+
module SequenceLike
|
4
|
+
def sequence_enum
|
5
|
+
raise NotImplementedError
|
6
|
+
end
|
7
|
+
|
8
|
+
def sequence_size
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
|
12
|
+
def append(other)
|
13
|
+
XDM::Value.create([self, other])
|
14
|
+
end
|
15
|
+
|
16
|
+
alias_method :<<, :append
|
17
|
+
alias_method :+, :append
|
18
|
+
end
|
19
|
+
|
20
|
+
module ItemSequenceLike
|
21
|
+
def sequence_enum
|
22
|
+
[self].to_enum
|
23
|
+
end
|
24
|
+
|
25
|
+
def sequence_size
|
26
|
+
1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require_relative '../s9api'
|
2
|
+
require_relative 'sequence_like'
|
3
|
+
|
4
|
+
module Saxon
|
5
|
+
module XDM
|
6
|
+
# An XPath Data Model Value object, representing a Sequence.
|
7
|
+
class Value
|
8
|
+
include XDM::SequenceLike
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# Create a new XDM::Value sequence containing the items passed in as a Ruby enumerable.
|
13
|
+
#
|
14
|
+
# @param items [Enumerable] A list of members
|
15
|
+
# @return [Saxon::XDM::Value] The XDM value
|
16
|
+
def create(*items)
|
17
|
+
items = items.flatten
|
18
|
+
case items.size
|
19
|
+
when 0
|
20
|
+
XDM.EmptySequence()
|
21
|
+
when 1
|
22
|
+
if existing_value = maybe_xdm_value(items.first)
|
23
|
+
return existing_value
|
24
|
+
end
|
25
|
+
XDM.Item(items.first)
|
26
|
+
else
|
27
|
+
new(Saxon::S9API::XdmValue.new(wrap_items(items)))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def maybe_xdm_value(item)
|
34
|
+
return item if item.is_a?(self)
|
35
|
+
return new(item) if item.instance_of?(Saxon::S9API::XdmValue)
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
def wrap_items(items)
|
40
|
+
result = []
|
41
|
+
items.map { |item|
|
42
|
+
wrap_item(item, result)
|
43
|
+
}
|
44
|
+
result
|
45
|
+
end
|
46
|
+
|
47
|
+
def wrap_item(item, result)
|
48
|
+
if item.respond_to?(:sequence_enum)
|
49
|
+
item.sequence_enum.each do |item|
|
50
|
+
result << item.to_java
|
51
|
+
end
|
52
|
+
elsif item.respond_to?(:each)
|
53
|
+
item.each do |item|
|
54
|
+
result << XDM.Item(item).to_java
|
55
|
+
end
|
56
|
+
else
|
57
|
+
result << XDM.Item(item).to_java
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_reader :s9_xdm_value
|
63
|
+
private :s9_xdm_value
|
64
|
+
|
65
|
+
# @api private
|
66
|
+
def initialize(s9_xdm_value)
|
67
|
+
@s9_xdm_value = s9_xdm_value
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [Fixnum] The size of the sequence
|
71
|
+
def size
|
72
|
+
s9_xdm_value.size
|
73
|
+
end
|
74
|
+
|
75
|
+
# Calls the given block once for each Item in the sequence, passing that
|
76
|
+
# item as a parameter. Returns the value itself.
|
77
|
+
#
|
78
|
+
# If no block is given, an Enumerator is returned.
|
79
|
+
#
|
80
|
+
# @overload
|
81
|
+
# @yield [item] The current XDM Item
|
82
|
+
# @yieldparam item [Saxon::XDM::AtomicValue, Saxon::XDM::Node] the item.
|
83
|
+
def each(&block)
|
84
|
+
to_enum.each(&block)
|
85
|
+
end
|
86
|
+
|
87
|
+
# @return [Saxon::S9API::XdmValue] The underlying Saxon Java XDM valuee object.
|
88
|
+
def to_java
|
89
|
+
@s9_xdm_value
|
90
|
+
end
|
91
|
+
|
92
|
+
# Compare this XDM::Value with another. Currently this requires iterating
|
93
|
+
# across the sequence, and the other sequence and comparing each member
|
94
|
+
# with the corresponding member in the other sequence.
|
95
|
+
#
|
96
|
+
# @param other [Saxon::XDM::Value] The XDM::Value to be compare against
|
97
|
+
# @return [Boolean] whether the two XDM::Values are equal
|
98
|
+
def ==(other)
|
99
|
+
return false unless other.is_a?(XDM::Value)
|
100
|
+
return false unless other.size == size
|
101
|
+
not_okay = to_enum.zip(other.to_enum).find { |mine, theirs|
|
102
|
+
mine != theirs
|
103
|
+
}
|
104
|
+
not_okay.nil? || !not_okay
|
105
|
+
end
|
106
|
+
|
107
|
+
alias_method :eql?, :==
|
108
|
+
|
109
|
+
# The hash code for the XDM::Value
|
110
|
+
# @return [Fixnum] The hash code
|
111
|
+
def hash
|
112
|
+
@hash ||= to_a.hash
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns a lazy Enumerator over the sequence
|
116
|
+
# @return [Enumerator::Lazy] the enumerator
|
117
|
+
def to_enum
|
118
|
+
s9_xdm_value.enum_for(:each).lazy.map { |s9_xdm_item|
|
119
|
+
XDM.Item(s9_xdm_item)
|
120
|
+
}.each
|
121
|
+
end
|
122
|
+
|
123
|
+
alias_method :enum_for, :to_enum
|
124
|
+
|
125
|
+
def sequence_enum
|
126
|
+
to_enum
|
127
|
+
end
|
128
|
+
|
129
|
+
def sequence_size
|
130
|
+
s9_xdm_value.size
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Placeholder class for Saxon Items that we haven't gotten to yet
|
135
|
+
class XDM::UnhandledItem
|
136
|
+
def initialize(s9_xdm_item)
|
137
|
+
@s9_xdm_item = s9_xdm_item
|
138
|
+
end
|
139
|
+
|
140
|
+
def to_java
|
141
|
+
@s9_xdm_item
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/lib/saxon/xpath.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require_relative './static_context'
|
3
|
+
require_relative './executable'
|
4
|
+
|
5
|
+
module Saxon
|
6
|
+
module XPath
|
7
|
+
# Compiles XPath expressions so they can be executed
|
8
|
+
class Compiler
|
9
|
+
# Create a new <tt>XPath::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 XPath compiler DSL block
|
15
|
+
# @return [Saxon::XPath::Compiler] the new compiler instance
|
16
|
+
def self.create(processor, &block)
|
17
|
+
static_context = XPath::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, :declared_namespaces, :declared_variables
|
36
|
+
# @!attribute [r] default_collation
|
37
|
+
# @return [String] the URI of the default declared collation
|
38
|
+
# @!attribute [r] declared_namespaces
|
39
|
+
# @return [Hash<String => String>] declared namespaces as prefix => URI hash
|
40
|
+
# @!attribute [r] declared_variables
|
41
|
+
# @return [Hash<Saxon::QName => Saxon::XPath::VariableDeclaration>] declared variables as QName => Declaration hash
|
42
|
+
|
43
|
+
# @param expression [String] the XPath expression to compile
|
44
|
+
# @return [Saxon::XPath::Executable] the executable query
|
45
|
+
def compile(expression)
|
46
|
+
Saxon::XPath::Executable.new(new_compiler.compile(expression), static_context)
|
47
|
+
end
|
48
|
+
|
49
|
+
def create(&block)
|
50
|
+
new_static_context = static_context.define(block)
|
51
|
+
self.class.new(@s9_processor, new_static_context)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def new_compiler
|
57
|
+
compiler = @s9_processor.newXPathCompiler
|
58
|
+
declared_namespaces.each do |prefix, uri|
|
59
|
+
compiler.declareNamespace(prefix, uri)
|
60
|
+
end
|
61
|
+
declared_variables.each do |_, decl|
|
62
|
+
compiler.declareVariable(*decl.compiler_args)
|
63
|
+
end
|
64
|
+
compiler.declareDefaultCollation(default_collation) unless default_collation.nil?
|
65
|
+
compiler
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative '../xdm'
|
2
|
+
|
3
|
+
module Saxon
|
4
|
+
module XPath
|
5
|
+
# Represents a compiled XPath query ready to be executed
|
6
|
+
class Executable
|
7
|
+
# @return [XPath::StaticContext] the XPath's static context
|
8
|
+
attr_reader :static_context
|
9
|
+
|
10
|
+
# @api private
|
11
|
+
# @param s9_xpath_executable [net.sf.saxon.s9api.XPathExecutable] the
|
12
|
+
# Saxon compiled XPath object
|
13
|
+
# @param static_context [XPath::StaticContext] the XPath's static
|
14
|
+
# context
|
15
|
+
def initialize(s9_xpath_executable, static_context)
|
16
|
+
@s9_xpath_executable, @static_context = s9_xpath_executable, static_context
|
17
|
+
end
|
18
|
+
|
19
|
+
# Run the compiled query using a passed-in node as the context item.
|
20
|
+
# @param context_item [Saxon::XDM::Node] the context item node
|
21
|
+
# @return [Saxon::XPath::Result] the result of the query as an
|
22
|
+
# enumerable
|
23
|
+
def run(context_item, variables = {})
|
24
|
+
selector = to_java.load
|
25
|
+
selector.setContextItem(context_item.to_java)
|
26
|
+
variables.each do |qname_or_string, value|
|
27
|
+
selector.setVariable(static_context.resolve_variable_qname(qname_or_string).to_java, Saxon::XDM.Value(value).to_java)
|
28
|
+
end
|
29
|
+
Result.new(selector.iterator)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [net.sf.saxon.s9api.XPathExecutable] the underlying Saxon
|
33
|
+
# <tt>XPathExecutable</tt>
|
34
|
+
def to_java
|
35
|
+
@s9_xpath_executable
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# The result of executing an XPath query as an enumerable object
|
40
|
+
class Result
|
41
|
+
include Enumerable
|
42
|
+
|
43
|
+
# @api private
|
44
|
+
# @param result_iterator [java.util.Iterator] the result of calling
|
45
|
+
# <tt>#iterator</tt> on a Saxon <tt>XPathSelector</tt>
|
46
|
+
def initialize(result_iterator)
|
47
|
+
@result_iterator = result_iterator
|
48
|
+
end
|
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)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,161 @@
|
|
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
|
+
Saxon::QName.resolve(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
|