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 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