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/qname.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'saxon/s9api'
|
2
|
+
|
3
|
+
module Saxon
|
4
|
+
# Represents QNames
|
5
|
+
class QName
|
6
|
+
def self.clark(clark_string)
|
7
|
+
s9_qname = Saxon::S9API::QName.fromClarkName(clark_string)
|
8
|
+
new(s9_qname)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.eqname(eqname_string)
|
12
|
+
s9_qname = Saxon::S9API::QName.fromEQName(eqname_string)
|
13
|
+
new(s9_qname)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.create(opts = {})
|
17
|
+
prefix = opts[:prefix]
|
18
|
+
uri = opts[:uri]
|
19
|
+
begin
|
20
|
+
local_name = opts.fetch(:local_name)
|
21
|
+
rescue KeyError
|
22
|
+
raise ArgumentError, "The :local_name option must be passed"
|
23
|
+
end
|
24
|
+
|
25
|
+
s9_qname = Saxon::S9API::QName.new(*[prefix, uri, local_name].compact)
|
26
|
+
new(s9_qname)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Resolve a QName string into a {Saxon::QName}.
|
30
|
+
#
|
31
|
+
# If the arg is a {Saxon::QName} already, it just gets returned. If
|
32
|
+
# it's an instance of the underlying Saxon Java QName, it'll be wrapped
|
33
|
+
# into a {Saxon::QName}
|
34
|
+
#
|
35
|
+
# If the arg is a string, it's resolved by using {resolve_variable_name}
|
36
|
+
#
|
37
|
+
# @param qname_or_string [String, Symbol, Saxon::QName] the qname to resolve
|
38
|
+
# @param namespaces [Hash<String => String>] the set of namespaces as a hash of <tt>"prefix" => "namespace-uri"</tt>
|
39
|
+
# @return [Saxon::QName]
|
40
|
+
def self.resolve(qname_or_string, namespaces = {})
|
41
|
+
case qname_or_string
|
42
|
+
when String, Symbol
|
43
|
+
resolve_qname_string(qname_or_string, namespaces)
|
44
|
+
when self
|
45
|
+
qname_or_string
|
46
|
+
when Saxon::S9API::QName
|
47
|
+
new(qname_or_string)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Resolve a QName string of the form <tt>"prefix:local-name"</tt> into a
|
52
|
+
# {Saxon::QName} by looking up the namespace URI in a hash of
|
53
|
+
# <tt>"prefix" => "namespace-uri"</tt>
|
54
|
+
#
|
55
|
+
# @param qname_string [String, Symbol] the QName as a <tt>"prefix:local-name"</tt> string
|
56
|
+
# @param namespaces [Hash<String => String>] the set of namespaces as a hash of <tt>"prefix" => "namespace-uri"</tt>
|
57
|
+
# @return [Saxon::QName]
|
58
|
+
def self.resolve_qname_string(qname_string, namespaces = {})
|
59
|
+
local_name, prefix = qname_string.to_s.split(':').reverse
|
60
|
+
uri = nil
|
61
|
+
|
62
|
+
if prefix
|
63
|
+
uri = namespaces[prefix]
|
64
|
+
raise self::PrefixedStringWithoutNSURIError.new(qname_string, prefix) if uri.nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
create(prefix: prefix, uri: uri, local_name: local_name)
|
68
|
+
end
|
69
|
+
|
70
|
+
attr_reader :s9_qname
|
71
|
+
private :s9_qname
|
72
|
+
|
73
|
+
# @api private
|
74
|
+
def initialize(s9_qname)
|
75
|
+
@s9_qname = s9_qname
|
76
|
+
end
|
77
|
+
|
78
|
+
# @return [String] The local name part of the QName
|
79
|
+
def local_name
|
80
|
+
@s9_qname.getLocalName
|
81
|
+
end
|
82
|
+
|
83
|
+
# @return [String] The prefix part of the QName ('' if unset)
|
84
|
+
def prefix
|
85
|
+
@s9_qname.getPrefix
|
86
|
+
end
|
87
|
+
|
88
|
+
# @return [String] The namespace URI part of the QName ('' if unset)
|
89
|
+
def uri
|
90
|
+
@s9_qname.getNamespaceURI
|
91
|
+
end
|
92
|
+
|
93
|
+
# Return a Clark notation representation of the QName:
|
94
|
+
#
|
95
|
+
# "{http://ns.url}local-name"
|
96
|
+
#
|
97
|
+
# Note that the prefix is lost in Clark notation.
|
98
|
+
# @return [String] The QName represented using Clark notation.
|
99
|
+
def clark
|
100
|
+
@s9_qname.getClarkName
|
101
|
+
end
|
102
|
+
|
103
|
+
# Return a Extended QName notation representation of the QName:
|
104
|
+
#
|
105
|
+
# "Q{http://ns.url}local-name"
|
106
|
+
#
|
107
|
+
# Note that the prefix is lost in EQName notation.
|
108
|
+
# @return [String] The QName represented using EQName notation.
|
109
|
+
def eqname
|
110
|
+
@s9_qname.getEQName
|
111
|
+
end
|
112
|
+
|
113
|
+
def ==(other)
|
114
|
+
return false unless other.is_a?(QName)
|
115
|
+
s9_qname.equals(other.to_java)
|
116
|
+
end
|
117
|
+
alias_method :eql?, :==
|
118
|
+
|
119
|
+
def hash
|
120
|
+
@hash ||= (local_name + uri).hash
|
121
|
+
end
|
122
|
+
|
123
|
+
# @return [Saxon::S9API::QName] the underlying Saxon QName object
|
124
|
+
def to_java
|
125
|
+
s9_qname
|
126
|
+
end
|
127
|
+
|
128
|
+
# convert the QName to a lexical string, using the prefix (if there is one).
|
129
|
+
# So, <tt>Saxon::QName.clark('{http://example.org/#ns}hello').to_s</tt>
|
130
|
+
# returns <tt>'hello'</tt>, and <tt>Saxon::QName.create(prefix: 'pre', uri:
|
131
|
+
# 'http://example.org/#ns', local_name: 'hello').to_s</tt> returns
|
132
|
+
# <tt>'pre:hello'</tt>
|
133
|
+
def to_s
|
134
|
+
s9_qname.to_s
|
135
|
+
end
|
136
|
+
|
137
|
+
def inspect
|
138
|
+
"<Saxon::QName @prefix=#{prefix} @uri=#{uri} @local_name=#{local_name}>"
|
139
|
+
end
|
140
|
+
|
141
|
+
# Raised when an attempt is made to resolve a <tt>prefix:local-name</tt>
|
142
|
+
# into a QName, and the prefix has not been bound to a namespace URI.
|
143
|
+
class PrefixedStringWithoutNSURIError < RuntimeError
|
144
|
+
def initialize(qname_string, prefix)
|
145
|
+
@qname_string, @prefix = qname_string, prefix
|
146
|
+
end
|
147
|
+
|
148
|
+
def to_s
|
149
|
+
"Namespace prefix ‘#{@prefix}’ for QName ‘#{@qname_string}’ is not bound to a URI"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
data/lib/saxon/s9api.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'saxon/loader'
|
2
|
+
|
3
|
+
module Saxon
|
4
|
+
module S9API
|
5
|
+
CLASS_IMPORT_SEMAPHORE = Mutex.new
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def const_missing(name)
|
9
|
+
Saxon::Loader.load!
|
10
|
+
begin
|
11
|
+
const_set(name, imported_classes.const_get(name))
|
12
|
+
rescue NameError
|
13
|
+
msg = "uninitialized constant Saxon::S9API::#{name}"
|
14
|
+
e = NameError.new(msg, name)
|
15
|
+
raise e
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def imported_classes
|
22
|
+
return @imported_classes if instance_variable_defined?(:@imported_classes)
|
23
|
+
CLASS_IMPORT_SEMAPHORE.synchronize do
|
24
|
+
@imported_classes = Module.new {
|
25
|
+
include_package 'net.sf.saxon.s9api'
|
26
|
+
java_import Java::net.sf.saxon.Configuration
|
27
|
+
java_import Java::net.sf.saxon.lib.FeatureKeys
|
28
|
+
java_import Java::net.sf.saxon.lib.ParseOptions
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'saxon/s9api'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module Saxon
|
5
|
+
# Serialize XDM objects.
|
6
|
+
class Serializer
|
7
|
+
# Manage access to the serialization properties of this serializer, with
|
8
|
+
# hash-like access.
|
9
|
+
#
|
10
|
+
# Properties can be set explicitly through this API, or via XSLT or XQuery
|
11
|
+
# serialization options like `<xsl:output>`.
|
12
|
+
#
|
13
|
+
# Properties set explicitly here will override properties set through the
|
14
|
+
# document like `<xsl:output>`.
|
15
|
+
class OutputProperties
|
16
|
+
# @api private
|
17
|
+
# Provides mapping between symbols and the underlying Saxon property
|
18
|
+
# instances
|
19
|
+
def self.output_properties
|
20
|
+
@output_properties ||= Hash[
|
21
|
+
Saxon::S9API::Serializer::Property.values.map { |property|
|
22
|
+
qname = property.getQName
|
23
|
+
key = [
|
24
|
+
qname.getPrefix,
|
25
|
+
qname.getLocalName.tr('-', '_')
|
26
|
+
].reject { |str| str == '' }.join('_').to_sym
|
27
|
+
[key, property]
|
28
|
+
}
|
29
|
+
]
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :s9_serializer
|
33
|
+
|
34
|
+
# @api private
|
35
|
+
def initialize(s9_serializer)
|
36
|
+
@s9_serializer = s9_serializer
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param [Symbol, Saxon::S9API::Serializer::Property] property The property to fetch
|
40
|
+
def [](property)
|
41
|
+
s9_serializer.getOutputProperty(resolved_property(property))
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param [Symbol, Saxon::S9API::Serializer::Property] property The property to set
|
45
|
+
# @param [String] value The string value of the property
|
46
|
+
def []=(property, value)
|
47
|
+
s9_serializer.setOutputProperty(resolved_property(property), value)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @overload fetch(property)
|
51
|
+
# @param [Symbol, Saxon::S9API::Serializer::Property] property The property to fetch
|
52
|
+
# @overload fetch(property, default)
|
53
|
+
# @param property [Symbol, Saxon::S9API::Serializer::Property] The property to fetch
|
54
|
+
# @param default [Object] The value to return if the property is unset
|
55
|
+
def fetch(property, default = nil)
|
56
|
+
explicit_value = self[property]
|
57
|
+
if explicit_value.nil? && !default.nil?
|
58
|
+
default
|
59
|
+
else
|
60
|
+
explicit_value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def resolved_property(property_key)
|
66
|
+
case property_key
|
67
|
+
when Symbol
|
68
|
+
self.class.output_properties.fetch(property_key)
|
69
|
+
else
|
70
|
+
property_key
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
attr_reader :s9_serializer
|
76
|
+
private :s9_serializer
|
77
|
+
|
78
|
+
# @api private
|
79
|
+
def initialize(s9_serializer)
|
80
|
+
@s9_serializer = s9_serializer
|
81
|
+
end
|
82
|
+
|
83
|
+
# @return [Saxon::Serializer::OutputProperties] hash-like access to the Output Properties
|
84
|
+
def output_property
|
85
|
+
@output_property ||= OutputProperties.new(s9_serializer)
|
86
|
+
end
|
87
|
+
|
88
|
+
# @overload serialize(xdm_value, io)
|
89
|
+
# Serialize an XdmValue to an IO
|
90
|
+
# @param [Saxon::XdmValue] xdm_value The XdmValue to serialize
|
91
|
+
# @param [File, IO] io The IO to serialize to
|
92
|
+
# @return [nil]
|
93
|
+
# @overload serialize(xdm_value, path)
|
94
|
+
# Serialize an XdmValue to file <tt>path</tt>
|
95
|
+
# @param [Saxon::XdmValue] xdm_value The XdmValue to serialize
|
96
|
+
# @param [String, Pathname] path The path of the file to serialize to
|
97
|
+
# @return [nil]
|
98
|
+
# @overload serialize(xdm_value)
|
99
|
+
# Serialize an XdmValue to a String
|
100
|
+
# @param [Saxon::XdmValue] xdm_value The XdmValue to serialize
|
101
|
+
# @return [String] The serialized XdmValue
|
102
|
+
def serialize(xdm_value, io_or_path = nil)
|
103
|
+
case io_or_path
|
104
|
+
when nil
|
105
|
+
serialize_to_string(xdm_value)
|
106
|
+
when String, Pathname
|
107
|
+
serialize_to_file(xdm_value, io_or_path)
|
108
|
+
else
|
109
|
+
serialize_to_io(xdm_value, io_or_path)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# @return [Saxon::S9API::Serializer] The underlying Saxon Serializer object
|
114
|
+
def to_java
|
115
|
+
s9_serializer
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def serialize_to_io(xdm_value, io)
|
121
|
+
s9_serializer.setOutputStream(io.to_outputstream)
|
122
|
+
s9_serializer.serializeXdmValue(xdm_value.to_java)
|
123
|
+
nil
|
124
|
+
end
|
125
|
+
|
126
|
+
def serialize_to_string(xdm_value)
|
127
|
+
str_encoding = output_property.fetch(:encoding, Encoding.default_internal || Encoding.default_external)
|
128
|
+
StringIO.open { |io|
|
129
|
+
io.binmode
|
130
|
+
serialize_to_io(xdm_value, io)
|
131
|
+
io.string.force_encoding(str_encoding)
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
def serialize_to_file(xdm_value, path)
|
136
|
+
file = Java::JavaIO::File.new(path)
|
137
|
+
s9_serializer.setOutputFile(file)
|
138
|
+
s9_serializer.serializeXdmValue(xdm_value.to_java)
|
139
|
+
nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
data/lib/saxon/source.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'java'
|
2
|
+
require 'saxon/jaxp'
|
3
|
+
require 'uri'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module Saxon
|
7
|
+
# Provides a wrapper around the JAXP StreamSource class Saxon uses to bring
|
8
|
+
# the XML bytestream in. Provides some extra methods to make handling closing
|
9
|
+
# the source and its inputstream after consumption more idiomatic
|
10
|
+
class Source
|
11
|
+
module Helpers
|
12
|
+
# Given a File, or IO object which will return either #path or
|
13
|
+
# #base_uri, return the #base_uri, if present, or the #path, if present, or
|
14
|
+
# nil
|
15
|
+
# @param [File, IO] io A File or IO
|
16
|
+
# object representing the input XML file or data, or a String containing
|
17
|
+
# the XML
|
18
|
+
# @return [String, nil] the path or URI from the IO (or nil if there is none)
|
19
|
+
def self.base_uri(io)
|
20
|
+
if io.respond_to?(:base_uri)
|
21
|
+
return io.base_uri.to_s
|
22
|
+
end
|
23
|
+
io.path if io.respond_to?(:path)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Given a File or IO return a Java InputStream
|
27
|
+
# @param [File, IO, org.jruby.util.IOInputStream, java.io.InputStream]
|
28
|
+
# io input to be converted to an input stream
|
29
|
+
# @return [java.io.InputStream] the wrapped input
|
30
|
+
def self.inputstream(io)
|
31
|
+
case io
|
32
|
+
when org.jruby.util.IOInputStream, java.io.InputStream
|
33
|
+
io
|
34
|
+
else
|
35
|
+
io.to_inputstream if io.respond_to?(:read)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Given a path return a Java File object
|
40
|
+
# @param [String, Pathname] path the path to the file
|
41
|
+
# @return [java.io.File] the Java File object
|
42
|
+
def self.file(path)
|
43
|
+
java.io.File.new(path.to_s)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
PathChecker = ->(path) {
|
48
|
+
File.file?(path)
|
49
|
+
}
|
50
|
+
URIChecker = ->(uri) {
|
51
|
+
begin
|
52
|
+
URI.parse(uri)
|
53
|
+
true
|
54
|
+
rescue URI::InvalidURIError
|
55
|
+
false
|
56
|
+
end
|
57
|
+
}
|
58
|
+
|
59
|
+
# Generate a Saxon::Source given an IO-like
|
60
|
+
#
|
61
|
+
# @param [IO, File] io The IO-like containing XML to be parsed
|
62
|
+
# @param [Hash] opts
|
63
|
+
# @option opts [String] :base_uri The Base URI for the Source - an
|
64
|
+
# absolute URI or relative path that will be used to resolve relative
|
65
|
+
# URLs in the XML. Setting this will override any path or URI derived
|
66
|
+
# from the IO-like.
|
67
|
+
# @return [Saxon::Source] the Saxon::Source wrapping the input
|
68
|
+
def self.from_io(io, opts = {})
|
69
|
+
base_uri = opts.fetch(:base_uri) { Helpers.base_uri(io) }
|
70
|
+
inputstream = Helpers.inputstream(io)
|
71
|
+
stream_source = Saxon::JAXP::StreamSource.new(inputstream, base_uri)
|
72
|
+
new(stream_source, inputstream)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Generate a Saxon::Source given a path to a file
|
76
|
+
#
|
77
|
+
# @param [String, Pathname] path The path to the XML file to be parsed
|
78
|
+
# @param [Hash] opts
|
79
|
+
# @option opts [String] :base_uri The Base URI for the Source - an
|
80
|
+
# absolute URI or relative path that will be used to resolve relative
|
81
|
+
# URLs in the XML. Setting this will override the file path.
|
82
|
+
# @return [Saxon::Source] the Saxon::Source wrapping the input
|
83
|
+
def self.from_path(path, opts = {})
|
84
|
+
stream_source = Saxon::JAXP::StreamSource.new(Helpers.file(path))
|
85
|
+
stream_source.setSystemId(opts[:base_uri]) if opts[:base_uri]
|
86
|
+
new(stream_source)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Generate a Saxon::Source given a URI
|
90
|
+
#
|
91
|
+
# @param [String, URI] uri The URI to the XML file to be parsed
|
92
|
+
# @param [Hash] opts
|
93
|
+
# @option opts [String] :base_uri The Base URI for the Source - an
|
94
|
+
# absolute URI or relative path that will be used to resolve relative
|
95
|
+
# URLs in the XML. Setting this will override the given URI.
|
96
|
+
# @return [Saxon::Source] the Saxon::Source wrapping the input
|
97
|
+
def self.from_uri(uri, opts = {})
|
98
|
+
stream_source = Saxon::JAXP::StreamSource.new(uri.to_s)
|
99
|
+
stream_source.setSystemId(opts[:base_uri]) if opts[:base_uri]
|
100
|
+
new(stream_source)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Generate a Saxon::Source given a string containing XML
|
104
|
+
#
|
105
|
+
# @param [String] string The string containing XML to be parsed
|
106
|
+
# @param [Hash] opts
|
107
|
+
# @option opts [String] :base_uri The Base URI for the Source - an
|
108
|
+
# absolute URI or relative path that will be used to resolve relative
|
109
|
+
# URLs in the XML. This will be nil unless set.
|
110
|
+
# @return [Saxon::Source] the Saxon::Source wrapping the input
|
111
|
+
def self.from_string(string, opts = {})
|
112
|
+
reader = java.io.StringReader.new(string)
|
113
|
+
stream_source = Saxon::JAXP::StreamSource.new(reader)
|
114
|
+
stream_source.setSystemId(opts[:base_uri]) if opts[:base_uri]
|
115
|
+
new(stream_source, reader)
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.create(io_path_uri_or_string, opts = {})
|
119
|
+
case io_path_uri_or_string
|
120
|
+
when IO, File, java.io.InputStream, StringIO
|
121
|
+
from_io(io_path_uri_or_string, opts)
|
122
|
+
when Pathname, PathChecker
|
123
|
+
from_path(io_path_uri_or_string, opts)
|
124
|
+
when URIChecker
|
125
|
+
from_uri(io_path_uri_or_string, opts)
|
126
|
+
else
|
127
|
+
from_string(io_path_uri_or_string, opts)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
attr_reader :stream_source, :inputstream
|
132
|
+
private :stream_source, :inputstream
|
133
|
+
|
134
|
+
# @api private
|
135
|
+
# @param [java.xml.transform.stream.StreamSource] stream_source The Java JAXP StreamSource
|
136
|
+
# @param [java.io.InputStream, java.io.StringReader] inputstream The Java InputStream or StringReader
|
137
|
+
def initialize(stream_source, inputstream = nil)
|
138
|
+
@stream_source = stream_source
|
139
|
+
@inputstream = inputstream
|
140
|
+
@closed = false
|
141
|
+
end
|
142
|
+
|
143
|
+
# @return [String] The base URI of the Source
|
144
|
+
def base_uri
|
145
|
+
stream_source.getSystemId
|
146
|
+
end
|
147
|
+
|
148
|
+
# @param [String, URI] uri The URI to use as the Source's Base URI
|
149
|
+
# @return [String] The new base URI of the Source
|
150
|
+
def base_uri=(uri)
|
151
|
+
stream_source.setSystemId(uri.to_s)
|
152
|
+
base_uri
|
153
|
+
end
|
154
|
+
|
155
|
+
# Close the Source and its associated InputStream or Reader, allowing those
|
156
|
+
# resources to be freed.
|
157
|
+
# @return [TrueClass] Returns true
|
158
|
+
def close
|
159
|
+
inputstream.close
|
160
|
+
@closed = true
|
161
|
+
end
|
162
|
+
|
163
|
+
# @return [Boolean] Returns true if the source is closed, false otherwise
|
164
|
+
def closed?
|
165
|
+
@closed
|
166
|
+
end
|
167
|
+
|
168
|
+
# Yields itself and then closes itself. To be used by DocumentBuilders or
|
169
|
+
# other consumers, making it easy to ensure the source is closed after it
|
170
|
+
# has been consumed.
|
171
|
+
#
|
172
|
+
# @raise [Saxon::SourceClosedError] if the Source has already been closed
|
173
|
+
# @yield [source] Yields self to the block
|
174
|
+
def consume(&block)
|
175
|
+
raise SourceClosedError if closed?
|
176
|
+
block.call(self)
|
177
|
+
close
|
178
|
+
end
|
179
|
+
|
180
|
+
# @return [java.xml.transform.stream.StreamSource] The underlying JAXP StreamSource
|
181
|
+
def to_java
|
182
|
+
@stream_source
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
class SourceClosedError < Exception; end
|
187
|
+
end
|