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
data/lib/saxon/xdm.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'xdm/node'
|
2
|
+
require_relative 'xdm/atomic_value'
|
3
|
+
require_relative 'xdm/array'
|
4
|
+
require_relative 'xdm/map'
|
5
|
+
require_relative 'xdm/function_item'
|
6
|
+
require_relative 'xdm/external_object'
|
7
|
+
require_relative 'xdm/value'
|
8
|
+
require_relative 'xdm/empty_sequence'
|
9
|
+
require_relative 'xdm/item'
|
10
|
+
|
11
|
+
module Saxon
|
12
|
+
module XDM
|
13
|
+
class << self
|
14
|
+
def AtomicValue(*args)
|
15
|
+
XDM::AtomicValue.create(*args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def Value(*args)
|
19
|
+
XDM::Value.create(*args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def EmptySequence()
|
23
|
+
XDM::EmptySequence.create
|
24
|
+
end
|
25
|
+
|
26
|
+
def Array(*args)
|
27
|
+
XDM::Array.create(*args)
|
28
|
+
end
|
29
|
+
|
30
|
+
def Map(*args)
|
31
|
+
XDM::Map.create(*args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require_relative '../s9api'
|
2
|
+
require_relative 'sequence_like'
|
3
|
+
|
4
|
+
module Saxon
|
5
|
+
module XDM
|
6
|
+
# Represents an XDM Array
|
7
|
+
class Array
|
8
|
+
def self.create(array)
|
9
|
+
case array
|
10
|
+
when S9API::XdmArray
|
11
|
+
new(array)
|
12
|
+
else
|
13
|
+
new(S9API::XdmArray.new(array.map { |item|
|
14
|
+
XDM.Value(item).to_java
|
15
|
+
}))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
include SequenceLike
|
20
|
+
include ItemSequenceLike
|
21
|
+
include Enumerable
|
22
|
+
|
23
|
+
attr_reader :s9_xdm_array
|
24
|
+
private :s9_xdm_array
|
25
|
+
|
26
|
+
# @api private
|
27
|
+
def initialize(s9_xdm_array)
|
28
|
+
@s9_xdm_array = s9_xdm_array
|
29
|
+
end
|
30
|
+
|
31
|
+
def each(&block)
|
32
|
+
cached_array.each(&block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def [](i)
|
36
|
+
cached_array[i]
|
37
|
+
end
|
38
|
+
|
39
|
+
def length
|
40
|
+
s9_xdm_array.arrayLength
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :size, :length
|
44
|
+
|
45
|
+
# compares two {XDM::AtomicValue}s using the underlying Saxon and XDM
|
46
|
+
# comparision rules
|
47
|
+
#
|
48
|
+
# @param other [Saxon::XDM::AtomicValue]
|
49
|
+
# @return [Boolean]
|
50
|
+
def ==(other)
|
51
|
+
return false unless other.is_a?(XDM::Array)
|
52
|
+
return false if length != other.length
|
53
|
+
cached_array == other.to_a
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_a
|
57
|
+
cached_array
|
58
|
+
end
|
59
|
+
|
60
|
+
alias_method :eql?, :==
|
61
|
+
|
62
|
+
def hash
|
63
|
+
@hash ||= cached_array.hash
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_java
|
67
|
+
s9_xdm_array
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def cached_array
|
73
|
+
@cached_array ||= s9_xdm_array.asList.map { |s9_xdm_value| XDM.Value(s9_xdm_value) }.freeze
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require_relative 'sequence_like'
|
2
|
+
require_relative '../s9api'
|
3
|
+
require_relative '../qname'
|
4
|
+
require_relative '../item_type'
|
5
|
+
|
6
|
+
module Saxon
|
7
|
+
module XDM
|
8
|
+
# An XPath Data Model Node object, representing an XML document, or an element
|
9
|
+
# or one of the other node chunks in the XDM.
|
10
|
+
class AtomicValue
|
11
|
+
include XDM::SequenceLike
|
12
|
+
include XDM::ItemSequenceLike
|
13
|
+
|
14
|
+
# Error thrown when an attempt to create QName-holding XDM::AtomicValue is
|
15
|
+
# made using anything other than a {Saxon::QName} or s9api.QName instance.
|
16
|
+
#
|
17
|
+
# QNames are dependent on the namespace URI, which isn't present in the
|
18
|
+
# lexical string you normally see (e.g. <tt>prefix:name</tt>). Prefixes are
|
19
|
+
# only bound to a URI in the context of a particular document, so creating
|
20
|
+
# them imlpicitly through the XDM::AtomicValue creation process doesn't really
|
21
|
+
# work. They need to be created explicitly and then handed in to be wrapped.
|
22
|
+
class CannotCreateQNameFromString < StandardError
|
23
|
+
def to_s
|
24
|
+
"QName XDM::AtomicValues must be created using an instance of Saxon::QName, not a string like 'prefix:name': Prefix URI binding is undefined at this point"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# xs:NOTATION is another QName-holding XDM type. Unlike xs:QName, there
|
29
|
+
# isn't a way to create these outside of parsing an XML document within
|
30
|
+
# Saxon, so attempting to do so raises this error.
|
31
|
+
class NotationCannotBeDirectlyCreated < StandardError
|
32
|
+
def to_s
|
33
|
+
"xs:NOTATION XDM::AtomicValues cannot be directly created outside of XML parsing."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
XS_QNAME = ItemType.get_type('xs:QName')
|
38
|
+
XS_NOTATION = ItemType.get_type('xs:NOTATION')
|
39
|
+
|
40
|
+
class << self
|
41
|
+
# Convert a single Ruby value into an XDM::AtomicValue
|
42
|
+
#
|
43
|
+
# If no explicit {ItemType} is passed, the correct type is guessed based
|
44
|
+
# on the class of the value. (e.g. <tt>xs:date</tt> for {Date}.)
|
45
|
+
#
|
46
|
+
# Values are converted based on Ruby idioms and operations, so an explicit
|
47
|
+
# {ItemType} of <tt>xs:boolean</tt> will use truthyness to evaluate the
|
48
|
+
# value. This means that the Ruby string <tt>'false'</tt> will produce an
|
49
|
+
# <tt>xs:boolean</tt> whose value is <tt>true</tt>, because all strings
|
50
|
+
# are truthy. If you need to pass lexical strings unchanged, use
|
51
|
+
# {XDM::AtomicValue.from_lexical_string}.
|
52
|
+
#
|
53
|
+
# @param value [Object] the value to convert
|
54
|
+
#
|
55
|
+
# @param item_type [Saxon::ItemType, String] the value's type, as either
|
56
|
+
# an {ItemType} or a name (<tt>xs:date</tt>)
|
57
|
+
#
|
58
|
+
# @return [Saxon::XDM::AtomicValue]
|
59
|
+
def create(value, item_type = nil)
|
60
|
+
case value
|
61
|
+
when Saxon::S9API::XdmAtomicValue
|
62
|
+
new(value)
|
63
|
+
when XDM::AtomicValue
|
64
|
+
value
|
65
|
+
else
|
66
|
+
return create_implying_item_type(value) if item_type.nil?
|
67
|
+
|
68
|
+
item_type = ItemType.get_type(item_type)
|
69
|
+
|
70
|
+
return new(Saxon::S9API::XdmAtomicValue.new(value.to_java)) if item_type == XS_QNAME && value_is_qname?(value)
|
71
|
+
raise NotationCannotBeDirectlyCreated if item_type == XS_NOTATION
|
72
|
+
|
73
|
+
value_lexical_string = item_type.lexical_string(value)
|
74
|
+
new(new_s9_xdm_atomic_value(value_lexical_string, item_type))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# convert a lexical string representation of an XDM Atomic Value into an
|
79
|
+
# XDM::AtomicValue.
|
80
|
+
#
|
81
|
+
# Note that this skips all conversion and checking of the string before
|
82
|
+
# handing it off to Saxon.
|
83
|
+
#
|
84
|
+
# @param value [String] the lexical string representation of the value
|
85
|
+
# @param item_type [Saxon::ItemType, String] the value's type, as either
|
86
|
+
# an {ItemType} or a name (<tt>xs:date</tt>)
|
87
|
+
# @return [Saxon::XDM::AtomicValue]
|
88
|
+
def from_lexical_string(value, item_type)
|
89
|
+
item_type = ItemType.get_type(item_type)
|
90
|
+
raise CannotCreateQNameFromString if item_type == XS_QNAME
|
91
|
+
new(new_s9_xdm_atomic_value(value.to_s, item_type))
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def new_s9_xdm_atomic_value(value, item_type)
|
97
|
+
Saxon::S9API::XdmAtomicValue.new(value.to_java, item_type.to_java)
|
98
|
+
end
|
99
|
+
|
100
|
+
def create_implying_item_type(value)
|
101
|
+
return new(Saxon::S9API::XdmAtomicValue.new(value.to_java)) if value_is_qname?(value)
|
102
|
+
|
103
|
+
item_type = ItemType.get_type(value.class)
|
104
|
+
|
105
|
+
new(new_s9_xdm_atomic_value(item_type.lexical_string(value), item_type))
|
106
|
+
end
|
107
|
+
|
108
|
+
def value_is_qname?(value)
|
109
|
+
QName === value || S9API::QName === value
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
attr_reader :s9_xdm_atomic_value
|
114
|
+
private :s9_xdm_atomic_value
|
115
|
+
|
116
|
+
# @api private
|
117
|
+
def initialize(s9_xdm_atomic_value)
|
118
|
+
@s9_xdm_atomic_value = s9_xdm_atomic_value
|
119
|
+
end
|
120
|
+
|
121
|
+
# Return a {QName} representing the type of the value
|
122
|
+
#
|
123
|
+
# @return [Saxon::QName] the {QName} of the value's type
|
124
|
+
def type_name
|
125
|
+
@type_name ||= Saxon::QName.new(s9_xdm_atomic_value.getTypeName)
|
126
|
+
end
|
127
|
+
|
128
|
+
# @return [Saxon::S9API::XdmAtomicValue] The underlying Saxon Java XDM
|
129
|
+
# atomic value object.
|
130
|
+
def to_java
|
131
|
+
s9_xdm_atomic_value
|
132
|
+
end
|
133
|
+
|
134
|
+
# Return the value as a String. Like calling XPath's <tt>string()</tt>
|
135
|
+
# function.
|
136
|
+
#
|
137
|
+
# @return [String] The string representation of the value
|
138
|
+
def to_s
|
139
|
+
s9_xdm_atomic_value.toString
|
140
|
+
end
|
141
|
+
|
142
|
+
# @return [Saxon::ItemType] The ItemType of the value
|
143
|
+
def item_type
|
144
|
+
@item_type ||= Saxon::ItemType.get_type(Saxon::QName.resolve(s9_xdm_atomic_value.getTypeName))
|
145
|
+
end
|
146
|
+
|
147
|
+
# Return the value as an instance of the Ruby class that best represents the
|
148
|
+
# type of the value. Types with no sensible equivalent are returned as their
|
149
|
+
# lexical string form
|
150
|
+
#
|
151
|
+
# @return [Object] A Ruby object representation of the value
|
152
|
+
def to_ruby
|
153
|
+
@ruby_value ||= item_type.ruby_value(self).freeze
|
154
|
+
end
|
155
|
+
|
156
|
+
# compares two {XDM::AtomicValue}s using the underlying Saxon and XDM
|
157
|
+
# comparision rules
|
158
|
+
#
|
159
|
+
# @param other [Saxon::XDM::AtomicValue]
|
160
|
+
# @return [Boolean]
|
161
|
+
def ==(other)
|
162
|
+
return false unless other.is_a?(XDM::AtomicValue)
|
163
|
+
s9_xdm_atomic_value.equals(other.to_java)
|
164
|
+
end
|
165
|
+
|
166
|
+
alias_method :eql?, :==
|
167
|
+
|
168
|
+
def hash
|
169
|
+
@hash ||= s9_xdm_atomic_value.hashCode
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative '../s9api'
|
2
|
+
require_relative 'sequence_like'
|
3
|
+
|
4
|
+
module Saxon
|
5
|
+
module XDM
|
6
|
+
# Represents the empty sequence in XDM
|
7
|
+
class EmptySequence
|
8
|
+
def self.create
|
9
|
+
@instance ||= new
|
10
|
+
end
|
11
|
+
|
12
|
+
include SequenceLike
|
13
|
+
|
14
|
+
def sequence_enum
|
15
|
+
[].to_enum
|
16
|
+
end
|
17
|
+
|
18
|
+
def sequence_size
|
19
|
+
0
|
20
|
+
end
|
21
|
+
|
22
|
+
def ==(other)
|
23
|
+
other.class == self.class
|
24
|
+
end
|
25
|
+
|
26
|
+
alias_method :eql?, :==
|
27
|
+
|
28
|
+
def hash
|
29
|
+
[].hash
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_java
|
33
|
+
@s9_xdm_empty_sequence ||= Saxon::S9API::XdmEmptySequence.getInstance
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative '../s9api'
|
2
|
+
require_relative 'sequence_like'
|
3
|
+
|
4
|
+
module Saxon
|
5
|
+
module XDM
|
6
|
+
# Represents a Saxon XDM ExternalObject
|
7
|
+
class ExternalObject
|
8
|
+
include SequenceLike
|
9
|
+
include ItemSequenceLike
|
10
|
+
|
11
|
+
# @api private
|
12
|
+
def initialize(s9_xdm_external_object)
|
13
|
+
@s9_xdm_external_object = s9_xdm_external_object
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_java
|
17
|
+
@s9_xdm_external_object
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative '../s9api'
|
2
|
+
require_relative 'sequence_like'
|
3
|
+
|
4
|
+
module Saxon
|
5
|
+
module XDM
|
6
|
+
# Represents an XDM Function Item
|
7
|
+
class FunctionItem
|
8
|
+
include SequenceLike
|
9
|
+
include ItemSequenceLike
|
10
|
+
|
11
|
+
# @api private
|
12
|
+
def initialize(s9_xdm_function_item)
|
13
|
+
@s9_xdm_function_item = s9_xdm_function_item
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_java
|
17
|
+
@s9_xdm_function_item
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Saxon
|
2
|
+
module XDM
|
3
|
+
def self.Item(item)
|
4
|
+
case item
|
5
|
+
when Value, AtomicValue, Node, Array, Map, ExternalObject
|
6
|
+
item
|
7
|
+
when Saxon::S9API::XdmNode
|
8
|
+
Node.new(item)
|
9
|
+
when Saxon::S9API::XdmAtomicValue
|
10
|
+
AtomicValue.new(item)
|
11
|
+
when Saxon::S9API::XdmExternalObject
|
12
|
+
ExternalObject.new(item)
|
13
|
+
when Saxon::S9API::XdmArray
|
14
|
+
Array.new(item)
|
15
|
+
when Saxon::S9API::XdmMap
|
16
|
+
Map.new(item)
|
17
|
+
when Saxon::S9API::XdmValue
|
18
|
+
Value.new(item)
|
19
|
+
when ::Array
|
20
|
+
Array.create(item)
|
21
|
+
when ::Hash
|
22
|
+
Map.create(item)
|
23
|
+
else
|
24
|
+
if item.respond_to?(:each)
|
25
|
+
Array.create(item)
|
26
|
+
else
|
27
|
+
AtomicValue.create(item)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require_relative '../s9api'
|
2
|
+
require_relative 'sequence_like'
|
3
|
+
|
4
|
+
module Saxon
|
5
|
+
module XDM
|
6
|
+
# Represents an XDM Map
|
7
|
+
class Map
|
8
|
+
def self.create(hash)
|
9
|
+
case hash
|
10
|
+
when Saxon::S9API::XdmMap
|
11
|
+
new(hash)
|
12
|
+
else
|
13
|
+
new(S9API::XdmMap.new(Hash[
|
14
|
+
hash.map { |key, value|
|
15
|
+
[XDM.AtomicValue(key).to_java, XDM.Value(value).to_java]
|
16
|
+
}
|
17
|
+
]))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
include SequenceLike
|
22
|
+
include ItemSequenceLike
|
23
|
+
include Enumerable
|
24
|
+
|
25
|
+
attr_reader :s9_xdm_map
|
26
|
+
private :s9_xdm_map
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
def initialize(s9_xdm_map)
|
30
|
+
@s9_xdm_map = s9_xdm_map
|
31
|
+
end
|
32
|
+
|
33
|
+
def ==(other)
|
34
|
+
return false unless other.is_a?(self.class)
|
35
|
+
to_h == other.to_h
|
36
|
+
end
|
37
|
+
|
38
|
+
def [](key)
|
39
|
+
cached_hash[XDM.AtomicValue(key)]
|
40
|
+
end
|
41
|
+
|
42
|
+
def fetch(key, *args, &block)
|
43
|
+
cached_hash.fetch(XDM.AtomicValue(key), *args, &block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def each(&block)
|
47
|
+
cached_hash.each(&block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def select(&block)
|
51
|
+
self.class.create(each.select(&block).to_h)
|
52
|
+
end
|
53
|
+
|
54
|
+
def reject(&block)
|
55
|
+
self.class.create(each.reject(&block).to_h)
|
56
|
+
end
|
57
|
+
|
58
|
+
def merge(other)
|
59
|
+
self.class.create(to_h.merge(other.to_h))
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_java
|
63
|
+
@s9_xdm_map
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_h
|
67
|
+
cached_hash
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def cached_hash
|
73
|
+
@cached_hash ||= s9_xdm_map.entrySet.map { |entry| [XDM.AtomicValue(entry.getKey), XDM.Value(entry.getValue)] }.to_h.freeze
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|