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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +62 -0
  3. data/.gitignore +13 -0
  4. data/.rspec +3 -0
  5. data/.ruby-version +1 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +6 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +43 -0
  10. data/Rakefile +20 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/lib/net/sf/saxon/Saxon-HE/9.9.1-5/Saxon-HE-9.9.1-5.jar +0 -0
  14. data/lib/saxon.rb +6 -0
  15. data/lib/saxon/axis_iterator.rb +31 -0
  16. data/lib/saxon/configuration.rb +116 -0
  17. data/lib/saxon/document_builder.rb +28 -0
  18. data/lib/saxon/item_type.rb +290 -0
  19. data/lib/saxon/item_type/lexical_string_conversion.rb +383 -0
  20. data/lib/saxon/item_type/value_to_ruby.rb +78 -0
  21. data/lib/saxon/jaxp.rb +8 -0
  22. data/lib/saxon/loader.rb +93 -0
  23. data/lib/saxon/occurrence_indicator.rb +33 -0
  24. data/lib/saxon/parse_options.rb +127 -0
  25. data/lib/saxon/processor.rb +102 -0
  26. data/lib/saxon/qname.rb +153 -0
  27. data/lib/saxon/s9api.rb +34 -0
  28. data/lib/saxon/serializer.rb +143 -0
  29. data/lib/saxon/source.rb +187 -0
  30. data/lib/saxon/version.rb +3 -0
  31. data/lib/saxon/xdm.rb +35 -0
  32. data/lib/saxon/xdm/array.rb +77 -0
  33. data/lib/saxon/xdm/atomic_value.rb +173 -0
  34. data/lib/saxon/xdm/empty_sequence.rb +37 -0
  35. data/lib/saxon/xdm/external_object.rb +21 -0
  36. data/lib/saxon/xdm/function_item.rb +21 -0
  37. data/lib/saxon/xdm/item.rb +32 -0
  38. data/lib/saxon/xdm/map.rb +77 -0
  39. data/lib/saxon/xdm/node.rb +71 -0
  40. data/lib/saxon/xdm/sequence_like.rb +30 -0
  41. data/lib/saxon/xdm/value.rb +145 -0
  42. data/lib/saxon/xpath.rb +8 -0
  43. data/lib/saxon/xpath/compiler.rb +69 -0
  44. data/lib/saxon/xpath/executable.rb +58 -0
  45. data/lib/saxon/xpath/static_context.rb +161 -0
  46. data/lib/saxon/xpath/variable_declaration.rb +68 -0
  47. data/lib/saxon/xslt.rb +8 -0
  48. data/lib/saxon/xslt/compiler.rb +70 -0
  49. data/lib/saxon/xslt/evaluation_context.rb +165 -0
  50. data/lib/saxon/xslt/executable.rb +156 -0
  51. data/lib/saxon_jars.rb +10 -0
  52. data/saxon-rb.gemspec +39 -0
  53. data/saxon.gemspec +30 -0
  54. metadata +240 -0
@@ -0,0 +1,3 @@
1
+ module Saxon
2
+ VERSION = "0.4.0"
3
+ end
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