ruby_rnv 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 899300861f1a2b315f879d451a7a5ee472302fbdac26ea775a2e56e09793d98c
4
- data.tar.gz: 4f2139ddde96c34a077e124600bb7cbbb0e98ef5db5fe5c57066bdcc8fd4c089
3
+ metadata.gz: a6b0736317b7df5919818cfeee87155c51ec58018c4462ebf1909a587dc7315c
4
+ data.tar.gz: 0cadcded8c1682eb0efad0d14dafb3a1643fecafae41d3637f3a77c8cfa05ae3
5
5
  SHA512:
6
- metadata.gz: c9660b568d0a4fe092080bb095fd80125540ece28c669ecae73faa9391567a337fcd8799702b29bdcecd022b9613f76c3d9e6013f3c289000a5a98950bd67860
7
- data.tar.gz: 63924d0755a95489733c62ccde564260750dcfea5e0a366e26d6663178b00e47d6ee095f18b8cee293c7c4eba457746a86cb9eedb696c7e63321449cbbf89536
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 = 16; /* maximum number of candidates to display */
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>]
@@ -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, :required, :allowed
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
- (compact_allowed_set.length > 0 ? compact_expected_phrase(compact_allowed_set) + " allowed" : nil)].join("; ")
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 ||= @required.map{|r| compact_expected_to_s(r)}.compact.uniq
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 ||= @allowed.map{|r| compact_expected_to_s(r)}.compact.uniq
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, :pre_processor
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
- @document.start_tag(@pre_processor.tag(tag_name), @pre_processor.attributes(tag_attrs))
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 str
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 str
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.2
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-04-20 00:00:00.000000000 Z
11
+ date: 2021-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler