ruby_rnv 0.3.0 → 0.5.0
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/ext/rnv/extconf.rb +1 -1
- data/ext/rnv/ruby_rnv.c +88 -381
- data/ext/rnv/ruby_rnv.h +62 -0
- data/ext/rnv/ruby_rnv_err.c +548 -0
- data/ext/rnv/src/ary.c +1 -2
- data/ext/rnv/src/drv.c +78 -62
- data/ext/rnv/src/drv.h +3 -2
- data/ext/rnv/src/er.c +1 -1
- data/ext/rnv/src/er.h +1 -1
- data/ext/rnv/src/erbit.h +3 -0
- data/ext/rnv/src/rn.c +24 -26
- data/ext/rnv/src/rn.h +1 -1
- data/ext/rnv/src/rnc.c +28 -16
- data/ext/rnv/src/rnc.h +3 -23
- data/ext/rnv/src/rnd.c +24 -20
- data/ext/rnv/src/rnd.h +3 -2
- data/ext/rnv/src/rnl.c +24 -20
- data/ext/rnv/src/rnl.h +2 -3
- data/ext/rnv/src/rnv.c +20 -18
- data/ext/rnv/src/rnv.h +2 -2
- data/ext/rnv/src/rnx.c +15 -17
- data/ext/rnv/src/rnx.h +2 -3
- data/ext/rnv/src/rx.c +44 -32
- data/ext/rnv/src/rx.h +7 -8
- data/ext/rnv/src/sc.c +5 -0
- data/ext/rnv/src/sc.h +1 -0
- data/ext/rnv/src/type.h +61 -28
- data/ext/rnv/src/xcl.c +24 -27
- data/ext/rnv/src/xsd.c +10 -23
- data/ext/rnv/src/xsd.h +1 -2
- data/lib/rnv/data_type_library.rb +5 -7
- data/lib/rnv/error.rb +103 -3
- data/lib/rnv/validator.rb +75 -7
- metadata +4 -2
data/ext/rnv/src/xsd.h
CHANGED
@@ -14,10 +14,9 @@
|
|
14
14
|
#define XSD_ER_WS 5
|
15
15
|
#define XSD_ER_ENUM 6
|
16
16
|
|
17
|
-
extern void xsd_default_verror_handler(
|
17
|
+
extern void xsd_default_verror_handler(void *data, int erno, int (*handler)(void *data, int erno,char *format, va_list ap), va_list ap);
|
18
18
|
|
19
19
|
extern void xsd_init(rx_st_t *rx_st);
|
20
|
-
extern void xsd_clear(void);
|
21
20
|
|
22
21
|
extern int xsd_allows(rx_st_t *rx_st, char *typ,char *ps,char *s,int n);
|
23
22
|
extern int xsd_equal(rx_st_t *rx_st, char *typ,char *val,char *s,int n);
|
@@ -2,21 +2,19 @@ module RNV
|
|
2
2
|
# Datatype library callback object
|
3
3
|
# @see https://www.oasis-open.org/committees/relax-ng/spec-20010811.html#IDA1I1R
|
4
4
|
class DataTypeLibrary
|
5
|
-
# @param [String] typ
|
5
|
+
# @param [String] typ the data type
|
6
6
|
# @param [String] val
|
7
7
|
# @param [String] s
|
8
|
-
# @param [Integer] n
|
9
8
|
# @return [Boolean]
|
10
|
-
def equal(typ, val, s
|
9
|
+
def equal(typ, val, s)
|
11
10
|
true
|
12
11
|
end
|
13
12
|
|
14
|
-
# @param [String] typ
|
13
|
+
# @param [String] typ the data type
|
15
14
|
# @param [String] ps
|
16
|
-
# @param [String] s
|
17
|
-
# @param [Integer] n
|
15
|
+
# @param [String] s the value
|
18
16
|
# @return [Boolean]
|
19
|
-
def allows(typ, ps, s
|
17
|
+
def allows(typ, ps, s)
|
20
18
|
true
|
21
19
|
end
|
22
20
|
end
|
data/lib/rnv/error.rb
CHANGED
@@ -1,13 +1,113 @@
|
|
1
1
|
module RNV
|
2
2
|
class Error
|
3
|
+
attr_reader :original_message, :original_expected
|
4
|
+
attr_reader :ns_uri, :element, :attr, :value
|
5
|
+
attr_reader :xpath
|
6
|
+
|
7
|
+
# @return [String]
|
8
|
+
def message
|
9
|
+
@original_message
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
def expected
|
14
|
+
@original_expected
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [String]
|
18
|
+
def compact_message
|
19
|
+
case @code
|
20
|
+
when :rnv_er_elem
|
21
|
+
"element <#{@element}> is not allowed"
|
22
|
+
when :rnv_er_ufin
|
23
|
+
"element <#{@element}> is incomplete"
|
24
|
+
when :rnv_er_akey
|
25
|
+
"attribute #{@attr} is not allowed"
|
26
|
+
when :rnv_er_aval
|
27
|
+
"attribute #{@attr} has invalid value '#{@value}'"
|
28
|
+
when :rnv_er_amis
|
29
|
+
"element <#{@element}> attribute missing"
|
30
|
+
else
|
31
|
+
@original_message
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [String]
|
36
|
+
def compact_expected
|
37
|
+
[(compact_required_set.length > 0 ? compact_expected_phrase(compact_required_set) + " required" : nil),
|
38
|
+
(compact_allowed_set.length > 0 ? compact_expected_phrase(compact_allowed_set) + " allowed" : nil)].join("; ")
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param [String] data original content
|
42
|
+
# @return [String] context
|
43
|
+
def contextualize(data, max_len = 60)
|
44
|
+
out = ""
|
45
|
+
if data and @line
|
46
|
+
err_data = data.split("\n")[@line - 1]
|
47
|
+
if err_data && err_data.length > @col - 1
|
48
|
+
err_data.insert(@col - 1, "🢑")
|
49
|
+
|
50
|
+
start = 0
|
51
|
+
if @col > max_len
|
52
|
+
start = @col - max_len
|
53
|
+
end
|
54
|
+
out += (start > 0 ? "…" : "") + err_data[start..(@col + max_len)].strip + (@col + max_len < err_data.length ? "…" : "")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
out
|
58
|
+
end
|
59
|
+
|
3
60
|
# @return [String]
|
4
61
|
def to_s
|
5
|
-
"#{@line}:#{@col}:error: #{
|
62
|
+
"#{@line}:#{@col}:error: #{self.message}\n#{self.expected}"
|
6
63
|
end
|
7
64
|
|
8
65
|
# @return [String]
|
9
66
|
def inspect
|
10
|
-
"#<RNV::Error code: :#{@code}, message: '#{
|
67
|
+
"#<RNV::Error code: :#{@code}, message: '#{self.message}', expected: '#{self.expected}, line: #{@line}, column: #{@col}>"
|
68
|
+
end
|
69
|
+
|
70
|
+
def required
|
71
|
+
@required.select{|a| @attr ? a.first == :rn_p_attribute : true}
|
72
|
+
end
|
73
|
+
|
74
|
+
def allowed
|
75
|
+
@allowed.select{|a| @attr ? a.first == :rn_p_attribute : true}
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def compact_expected_to_s(e, with_ns = false)
|
81
|
+
case e.first
|
82
|
+
when :rn_p_attribute
|
83
|
+
compact_expected_to_s(e.last, with_ns)
|
84
|
+
when :rn_p_element
|
85
|
+
"<" + compact_expected_to_s(e.last, with_ns) + ">"
|
86
|
+
when :rn_p_data
|
87
|
+
compact_expected_to_s(e.last, with_ns)
|
88
|
+
when :rn_p_value
|
89
|
+
"\"#{e.last}\""
|
90
|
+
when :rn_nc_datatype
|
91
|
+
"datatype #{e[-2]}:#{e.last}"
|
92
|
+
when :rn_nc_qname
|
93
|
+
with_ns ? "#{e.first}:#{e.last}" : e.last
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def compact_required_set
|
98
|
+
@compact_required_set ||= required.map { |r| compact_expected_to_s(r) }.compact.uniq
|
99
|
+
end
|
100
|
+
|
101
|
+
def compact_allowed_set
|
102
|
+
@compact_allowed_set ||= allowed.map { |r| compact_expected_to_s(r) }.compact.uniq
|
103
|
+
end
|
104
|
+
|
105
|
+
def compact_expected_phrase(set)
|
106
|
+
if set.length > 1
|
107
|
+
set[0..-2].join(", ") + " or " + set.last
|
108
|
+
else
|
109
|
+
set.last
|
110
|
+
end
|
11
111
|
end
|
12
112
|
end
|
13
|
-
end
|
113
|
+
end
|
data/lib/rnv/validator.rb
CHANGED
@@ -3,36 +3,98 @@ require 'rnv/rnv'
|
|
3
3
|
require 'rnv/pre_processor'
|
4
4
|
|
5
5
|
module RNV
|
6
|
+
class DocumentEmpty < StandardError; end
|
7
|
+
|
8
|
+
# @!visibility private
|
9
|
+
class XpathNode
|
10
|
+
attr_accessor :name
|
11
|
+
attr_accessor :uri, :namespaces
|
12
|
+
attr_accessor :parent
|
13
|
+
attr_accessor :children
|
14
|
+
|
15
|
+
def initialize(name)
|
16
|
+
@name = name
|
17
|
+
@children = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_child(name, uri = nil, namespaces = {})
|
21
|
+
child = XpathNode.new(name)
|
22
|
+
child.uri = uri
|
23
|
+
child.namespaces = namespaces
|
24
|
+
child.parent = self
|
25
|
+
@children << child
|
26
|
+
child
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_xpath
|
30
|
+
xpath = []
|
31
|
+
current = self
|
32
|
+
namespaces = {}
|
33
|
+
rev_namespaces = {}
|
34
|
+
ns_current = self
|
35
|
+
while ns_current.name
|
36
|
+
ns_current.namespaces.each do |prefix, uri|
|
37
|
+
rev_namespaces[uri] ||= []
|
38
|
+
rev_namespaces[uri] << prefix
|
39
|
+
end
|
40
|
+
ns_current = ns_current.parent
|
41
|
+
end
|
42
|
+
|
43
|
+
rev_namespaces.each do |uri, prefixes|
|
44
|
+
if prefixes.length > 0
|
45
|
+
prefixes.select! { |prefix| prefix != "xmlns" }
|
46
|
+
end
|
47
|
+
namespaces[prefixes.first||"xmlns"] = uri
|
48
|
+
end
|
49
|
+
|
50
|
+
while current.name
|
51
|
+
xpath << "#{rev_namespaces[current.uri].first||"xmlns"}:#{current.name}[#{current.parent.children.select { |child| child.name == current.name }.index(current) + 1}]"
|
52
|
+
current = current.parent
|
53
|
+
end
|
54
|
+
[xpath.reverse, namespaces]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
6
58
|
# @!visibility private
|
7
59
|
class NokogiriSaxDocument < Nokogiri::XML::SAX::Document
|
8
60
|
# @return [Nokogiri::XML::SAX::ParserContext]
|
9
|
-
attr_accessor :ctx
|
61
|
+
attr_accessor :ctx
|
62
|
+
attr_accessor :pre_processor
|
63
|
+
|
10
64
|
# @param [RNV::Document] document
|
11
65
|
def initialize(document)
|
12
66
|
@document = document
|
67
|
+
@xpath_tree = XpathNode.new(nil)
|
13
68
|
end
|
14
69
|
|
15
70
|
def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = nil)
|
16
|
-
update_line_col
|
17
71
|
tag_attrs = attrs.map { |attr| [attr.uri ? "#{attr.uri}:#{attr.localname}" : attr.localname, attr.value] }
|
18
72
|
tag_name = uri ? "#{uri}:#{name}" : name
|
73
|
+
namespaces = {}
|
74
|
+
ns.each do |n|
|
75
|
+
namespaces[n.first || "xmlns"] = n.last
|
76
|
+
end
|
77
|
+
@xpath_tree = @xpath_tree.add_child(name, uri, namespaces)
|
78
|
+
|
79
|
+
update_line_col
|
19
80
|
@document.start_tag(@pre_processor.tag(tag_name), @pre_processor.attributes(tag_attrs))
|
20
81
|
end
|
21
82
|
|
22
83
|
def end_element_namespace(name, prefix = nil, uri = nil)
|
23
|
-
|
84
|
+
@xpath_tree = @xpath_tree.parent
|
24
85
|
tag_name = uri ? "#{uri}:#{name}" : name
|
86
|
+
update_line_col
|
25
87
|
@document.end_tag(@pre_processor.tag(tag_name))
|
26
88
|
end
|
27
89
|
|
28
|
-
def characters
|
90
|
+
def characters(value)
|
29
91
|
update_line_col
|
30
|
-
@document.characters(@pre_processor.text(
|
92
|
+
@document.characters(@pre_processor.text(value))
|
31
93
|
end
|
32
94
|
|
33
|
-
def cdata_block
|
95
|
+
def cdata_block(value)
|
34
96
|
update_line_col
|
35
|
-
@document.characters(@pre_processor.(
|
97
|
+
@document.characters(@pre_processor.text(value))
|
36
98
|
end
|
37
99
|
|
38
100
|
private
|
@@ -40,6 +102,8 @@ module RNV
|
|
40
102
|
def update_line_col
|
41
103
|
@document.last_line = @ctx.line
|
42
104
|
@document.last_col = @ctx.column
|
105
|
+
xpath = @xpath_tree.to_xpath
|
106
|
+
@document.xpath = ["/" + xpath.first.join("/"), xpath.last]
|
43
107
|
end
|
44
108
|
end
|
45
109
|
|
@@ -78,6 +142,8 @@ module RNV
|
|
78
142
|
rnv_doc = NokogiriSaxDocument.new(@document)
|
79
143
|
rnv_doc.pre_processor = pre_processor
|
80
144
|
|
145
|
+
raise RNV::DocumentEmpty if str.nil? or str.empty?
|
146
|
+
|
81
147
|
parser = Nokogiri::XML::SAX::Parser.new(rnv_doc)
|
82
148
|
parser.parse_memory(str) do |ctx|
|
83
149
|
ctx.replace_entities = true
|
@@ -98,6 +164,8 @@ module RNV
|
|
98
164
|
|
99
165
|
file = xml.is_a?(File) ? xml : File.open(xml)
|
100
166
|
|
167
|
+
raise RNV::DocumentEmpty if file.size == 0
|
168
|
+
|
101
169
|
parser = Nokogiri::XML::SAX::Parser.new(rnv_doc)
|
102
170
|
parser.parse(file) do |ctx|
|
103
171
|
ctx.replace_entities = true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_rnv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julien Boulnois
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -104,6 +104,8 @@ files:
|
|
104
104
|
- Gemfile
|
105
105
|
- ext/rnv/extconf.rb
|
106
106
|
- ext/rnv/ruby_rnv.c
|
107
|
+
- ext/rnv/ruby_rnv.h
|
108
|
+
- ext/rnv/ruby_rnv_err.c
|
107
109
|
- ext/rnv/src/ary.c
|
108
110
|
- ext/rnv/src/ary.h
|
109
111
|
- ext/rnv/src/drv.c
|