ruby_rnv 0.4.2 → 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/ruby_rnv.c +7 -1
- data/ext/rnv/ruby_rnv_err.c +7 -4
- data/lib/rnv/error.rb +19 -8
- data/lib/rnv/validator.rb +69 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6b0736317b7df5919818cfeee87155c51ec58018c4462ebf1909a587dc7315c
|
4
|
+
data.tar.gz: 0cadcded8c1682eb0efad0d14dafb3a1643fecafae41d3637f3a77c8cfa05ae3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7af568949b3eac5192f3bda69315b493fc0bf4509376b6930bedc0ab59768fe13ab01258cbec95dd922145c074f514d0e94517706f519abc1559538893729561
|
7
|
+
data.tar.gz: 50ca7148720191a98ed9428f12421cfc50323c7162bf84f43aa92713c7a3526fba2cb16c5d86d7fb7ccc7fbb4836afa9ab69cf64843711206bb7df9442dd37b5
|
data/ext/rnv/ruby_rnv.c
CHANGED
@@ -67,7 +67,7 @@ VALUE rb_document_init(VALUE self)
|
|
67
67
|
|
68
68
|
document->opened = document->ok = 0;
|
69
69
|
|
70
|
-
document->nexp =
|
70
|
+
document->nexp = 256; /* maximum number of candidates to display */
|
71
71
|
document->text = NULL;
|
72
72
|
|
73
73
|
rb_iv_set(self, "@errors", rb_ary_new2(0));
|
@@ -462,6 +462,12 @@ void Init_rnv()
|
|
462
462
|
*/
|
463
463
|
rb_define_attr(Document, "last_col", 1, 1);
|
464
464
|
|
465
|
+
/*
|
466
|
+
* xpath to node, set by SAX handler
|
467
|
+
* @return [String]
|
468
|
+
*/
|
469
|
+
rb_define_attr(Document, "xpath", 1, 1);
|
470
|
+
|
465
471
|
/*
|
466
472
|
* errors from current document
|
467
473
|
* @return [Array<RNV::Error>]
|
data/ext/rnv/ruby_rnv_err.c
CHANGED
@@ -439,7 +439,7 @@ static void ruby_parse_error(VALUE err_obj, int erno, va_list ap)
|
|
439
439
|
// return id;
|
440
440
|
}
|
441
441
|
|
442
|
-
VALUE ruby_create_error(VALUE self, VALUE line, VALUE col, int erno, char *format, va_list ap)
|
442
|
+
VALUE ruby_create_error(VALUE self, VALUE line, VALUE col, VALUE xpath, int erno, char *format, va_list ap)
|
443
443
|
{
|
444
444
|
VALUE err_class = Error;
|
445
445
|
VALUE err_obj = rb_class_new_instance(0, NULL, err_class);
|
@@ -463,6 +463,8 @@ VALUE ruby_create_error(VALUE self, VALUE line, VALUE col, int erno, char *forma
|
|
463
463
|
rb_iv_set(err_obj, "@line", line); // set line from sax parser
|
464
464
|
rb_iv_set(err_obj, "@col", col); // set col from sax parser
|
465
465
|
|
466
|
+
rb_iv_set(err_obj, "@xpath", xpath); // set line from sax parser
|
467
|
+
|
466
468
|
rb_iv_set(err_obj, "@required", rb_ary_new2(0));
|
467
469
|
rb_iv_set(err_obj, "@allowed", rb_ary_new2(0));
|
468
470
|
return err_obj;
|
@@ -481,7 +483,7 @@ int ruby_verror_handler(void *data, int erno, char *format, va_list ap)
|
|
481
483
|
|
482
484
|
if (erno & ERBIT_RNL || erno & ERBIT_RNC || erno & ERBIT_RND)
|
483
485
|
{
|
484
|
-
VALUE err_obj = ruby_create_error(self, INT2NUM(-1), INT2NUM(-1), erno, format, ap);
|
486
|
+
VALUE err_obj = ruby_create_error(self, INT2NUM(-1), INT2NUM(-1), Qnil, erno, format, ap);
|
485
487
|
rb_iv_set(err_obj, "@original_expected", rb_str_new2(""));
|
486
488
|
rb_ary_push(errors, err_obj);
|
487
489
|
}
|
@@ -491,14 +493,15 @@ int ruby_verror_handler(void *data, int erno, char *format, va_list ap)
|
|
491
493
|
VALUE r_last_col = rb_iv_get(self, "@last_col");
|
492
494
|
int last_line = NUM2INT(r_last_line);
|
493
495
|
int last_col = NUM2INT(r_last_col);
|
496
|
+
int xpath = NUM2INT(r_last_col);
|
494
497
|
|
495
498
|
// only one error per line/col
|
496
|
-
if (document->last_line != last_line || document->last_col != last_col)
|
499
|
+
// if (document->last_line != last_line || document->last_col != last_col)
|
497
500
|
{
|
498
501
|
document->last_line = last_line;
|
499
502
|
document->last_col = last_col;
|
500
503
|
|
501
|
-
VALUE err_obj = ruby_create_error(self, r_last_line, r_last_col, erno, format, ap);
|
504
|
+
VALUE err_obj = ruby_create_error(self, r_last_line, r_last_col, rb_iv_get(self, "@xpath"), erno, format, ap);
|
502
505
|
|
503
506
|
VALUE expected = rb_str_new2("");
|
504
507
|
|
data/lib/rnv/error.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module RNV
|
2
2
|
class Error
|
3
3
|
attr_reader :original_message, :original_expected
|
4
|
-
attr_reader :ns_uri, :element, :attr, :value
|
4
|
+
attr_reader :ns_uri, :element, :attr, :value
|
5
|
+
attr_reader :xpath
|
5
6
|
|
6
7
|
# @return [String]
|
7
8
|
def message
|
@@ -33,8 +34,8 @@ module RNV
|
|
33
34
|
|
34
35
|
# @return [String]
|
35
36
|
def compact_expected
|
36
|
-
[(compact_required_set.length > 0 ? compact_expected_phrase(compact_required_set) +" required" : nil),
|
37
|
-
|
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("; ")
|
38
39
|
end
|
39
40
|
|
40
41
|
# @param [String] data original content
|
@@ -43,7 +44,7 @@ module RNV
|
|
43
44
|
out = ""
|
44
45
|
if data and @line
|
45
46
|
err_data = data.split("\n")[@line - 1]
|
46
|
-
if err_data
|
47
|
+
if err_data && err_data.length > @col - 1
|
47
48
|
err_data.insert(@col - 1, "🢑")
|
48
49
|
|
49
50
|
start = 0
|
@@ -66,6 +67,14 @@ module RNV
|
|
66
67
|
"#<RNV::Error code: :#{@code}, message: '#{self.message}', expected: '#{self.expected}, line: #{@line}, column: #{@col}>"
|
67
68
|
end
|
68
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
|
+
|
69
78
|
private
|
70
79
|
|
71
80
|
def compact_expected_to_s(e, with_ns = false)
|
@@ -73,9 +82,11 @@ module RNV
|
|
73
82
|
when :rn_p_attribute
|
74
83
|
compact_expected_to_s(e.last, with_ns)
|
75
84
|
when :rn_p_element
|
76
|
-
"<"+compact_expected_to_s(e.last, with_ns)+">"
|
85
|
+
"<" + compact_expected_to_s(e.last, with_ns) + ">"
|
77
86
|
when :rn_p_data
|
78
87
|
compact_expected_to_s(e.last, with_ns)
|
88
|
+
when :rn_p_value
|
89
|
+
"\"#{e.last}\""
|
79
90
|
when :rn_nc_datatype
|
80
91
|
"datatype #{e[-2]}:#{e.last}"
|
81
92
|
when :rn_nc_qname
|
@@ -84,16 +95,16 @@ module RNV
|
|
84
95
|
end
|
85
96
|
|
86
97
|
def compact_required_set
|
87
|
-
@compact_required_set ||=
|
98
|
+
@compact_required_set ||= required.map { |r| compact_expected_to_s(r) }.compact.uniq
|
88
99
|
end
|
89
100
|
|
90
101
|
def compact_allowed_set
|
91
|
-
@compact_allowed_set ||=
|
102
|
+
@compact_allowed_set ||= allowed.map { |r| compact_expected_to_s(r) }.compact.uniq
|
92
103
|
end
|
93
104
|
|
94
105
|
def compact_expected_phrase(set)
|
95
106
|
if set.length > 1
|
96
|
-
set[0..-2].join(", ") + " or "+set.last
|
107
|
+
set[0..-2].join(", ") + " or " + set.last
|
97
108
|
else
|
98
109
|
set.last
|
99
110
|
end
|
data/lib/rnv/validator.rb
CHANGED
@@ -5,36 +5,96 @@ require 'rnv/pre_processor'
|
|
5
5
|
module RNV
|
6
6
|
class DocumentEmpty < StandardError; end
|
7
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
|
+
|
8
58
|
# @!visibility private
|
9
59
|
class NokogiriSaxDocument < Nokogiri::XML::SAX::Document
|
10
60
|
# @return [Nokogiri::XML::SAX::ParserContext]
|
11
|
-
attr_accessor :ctx
|
61
|
+
attr_accessor :ctx
|
62
|
+
attr_accessor :pre_processor
|
63
|
+
|
12
64
|
# @param [RNV::Document] document
|
13
65
|
def initialize(document)
|
14
66
|
@document = document
|
67
|
+
@xpath_tree = XpathNode.new(nil)
|
15
68
|
end
|
16
69
|
|
17
70
|
def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = nil)
|
18
71
|
tag_attrs = attrs.map { |attr| [attr.uri ? "#{attr.uri}:#{attr.localname}" : attr.localname, attr.value] }
|
19
72
|
tag_name = uri ? "#{uri}:#{name}" : name
|
20
|
-
|
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
|
+
|
21
79
|
update_line_col
|
80
|
+
@document.start_tag(@pre_processor.tag(tag_name), @pre_processor.attributes(tag_attrs))
|
22
81
|
end
|
23
82
|
|
24
83
|
def end_element_namespace(name, prefix = nil, uri = nil)
|
84
|
+
@xpath_tree = @xpath_tree.parent
|
25
85
|
tag_name = uri ? "#{uri}:#{name}" : name
|
26
|
-
@document.end_tag(@pre_processor.tag(tag_name))
|
27
86
|
update_line_col
|
87
|
+
@document.end_tag(@pre_processor.tag(tag_name))
|
28
88
|
end
|
29
89
|
|
30
|
-
def characters
|
31
|
-
@document.characters(@pre_processor.text(str))
|
90
|
+
def characters(value)
|
32
91
|
update_line_col
|
92
|
+
@document.characters(@pre_processor.text(value))
|
33
93
|
end
|
34
94
|
|
35
|
-
def cdata_block
|
36
|
-
@document.characters(@pre_processor.text(str))
|
95
|
+
def cdata_block(value)
|
37
96
|
update_line_col
|
97
|
+
@document.characters(@pre_processor.text(value))
|
38
98
|
end
|
39
99
|
|
40
100
|
private
|
@@ -42,6 +102,8 @@ module RNV
|
|
42
102
|
def update_line_col
|
43
103
|
@document.last_line = @ctx.line
|
44
104
|
@document.last_col = @ctx.column
|
105
|
+
xpath = @xpath_tree.to_xpath
|
106
|
+
@document.xpath = ["/" + xpath.first.join("/"), xpath.last]
|
45
107
|
end
|
46
108
|
end
|
47
109
|
|
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
|