ruby_rnv 0.4.2 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- 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 +25 -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: 4214fd7cf9852894c4b122a3d2d8bc15a87c4e0aa464bb3bcb359cfe0449c3a4
|
4
|
+
data.tar.gz: bbb487f231d7cf15affaaab7f794e656100f57a1022682994da12ceb0619b5fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c4d44f5a42521cda63da8f2e4c51b05e7812896e778da25ec1795b69af5f55e60ed58e542c58f96715e40fc697da4063eda47bff4165f68823edd4919c08c91
|
7
|
+
data.tar.gz: 8c62a8ba7a327c7728b647617f66c4c116a85391b73a72597c29475b8c2e67aa74ab4c73e3b363002027b6390b769c174f0836df6060521ace149370cf54a24c
|
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,27 +82,35 @@ 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
|
82
93
|
with_ns ? "#{e.first}:#{e.last}" : e.last
|
94
|
+
when :rn_p_text
|
95
|
+
"text"
|
96
|
+
when :rn_p_after
|
97
|
+
"after"
|
98
|
+
else
|
99
|
+
"unknown #{e.first}"
|
83
100
|
end
|
84
101
|
end
|
85
102
|
|
86
103
|
def compact_required_set
|
87
|
-
@compact_required_set ||=
|
104
|
+
@compact_required_set ||= required.map { |r| compact_expected_to_s(r) }.compact.uniq
|
88
105
|
end
|
89
106
|
|
90
107
|
def compact_allowed_set
|
91
|
-
@compact_allowed_set ||=
|
108
|
+
@compact_allowed_set ||= allowed.map { |r| compact_expected_to_s(r) }.compact.uniq
|
92
109
|
end
|
93
110
|
|
94
111
|
def compact_expected_phrase(set)
|
95
112
|
if set.length > 1
|
96
|
-
set[0..-2].join(", ") + " or "+set.last
|
113
|
+
set[0..-2].join(", ") + " or " + set.last
|
97
114
|
else
|
98
115
|
set.last
|
99
116
|
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
|
+
current_name_with_ns = "#{rev_namespaces[current.uri]&.first||"xmlns"}:#{current.name}"
|
52
|
+
xpath << "#{current_name_with_ns}[#{current.parent.children.select { |child| child.name == current.name }.index(current) + 1}]"
|
53
|
+
current = current.parent
|
54
|
+
end
|
55
|
+
[xpath.reverse, namespaces]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
8
59
|
# @!visibility private
|
9
60
|
class NokogiriSaxDocument < Nokogiri::XML::SAX::Document
|
10
61
|
# @return [Nokogiri::XML::SAX::ParserContext]
|
11
|
-
attr_accessor :ctx
|
62
|
+
attr_accessor :ctx
|
63
|
+
attr_accessor :pre_processor
|
64
|
+
|
12
65
|
# @param [RNV::Document] document
|
13
66
|
def initialize(document)
|
14
67
|
@document = document
|
68
|
+
@xpath_tree = XpathNode.new(nil)
|
15
69
|
end
|
16
70
|
|
17
71
|
def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = nil)
|
18
72
|
tag_attrs = attrs.map { |attr| [attr.uri ? "#{attr.uri}:#{attr.localname}" : attr.localname, attr.value] }
|
19
73
|
tag_name = uri ? "#{uri}:#{name}" : name
|
20
|
-
|
74
|
+
namespaces = {}
|
75
|
+
ns.each do |n|
|
76
|
+
namespaces[n.first || "xmlns"] = n.last
|
77
|
+
end
|
78
|
+
@xpath_tree = @xpath_tree.add_child(name, uri, namespaces)
|
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)
|
25
84
|
tag_name = uri ? "#{uri}:#{name}" : name
|
26
|
-
@document.end_tag(@pre_processor.tag(tag_name))
|
27
85
|
update_line_col
|
86
|
+
@document.end_tag(@pre_processor.tag(tag_name))
|
87
|
+
@xpath_tree = @xpath_tree.parent
|
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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julien Boulnois
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-09-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|