ruby_rnv 0.4.2 → 0.5.2

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: 4214fd7cf9852894c4b122a3d2d8bc15a87c4e0aa464bb3bcb359cfe0449c3a4
4
+ data.tar.gz: bbb487f231d7cf15affaaab7f794e656100f57a1022682994da12ceb0619b5fc
5
5
  SHA512:
6
- metadata.gz: c9660b568d0a4fe092080bb095fd80125540ece28c669ecae73faa9391567a337fcd8799702b29bdcecd022b9613f76c3d9e6013f3c289000a5a98950bd67860
7
- data.tar.gz: 63924d0755a95489733c62ccde564260750dcfea5e0a366e26d6663178b00e47d6ee095f18b8cee293c7c4eba457746a86cb9eedb696c7e63321449cbbf89536
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 = 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,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 ||= @required.map{|r| compact_expected_to_s(r)}.compact.uniq
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 ||= @allowed.map{|r| compact_expected_to_s(r)}.compact.uniq
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, :pre_processor
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
- @document.start_tag(@pre_processor.tag(tag_name), @pre_processor.attributes(tag_attrs))
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 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.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: 2021-04-20 00:00:00.000000000 Z
11
+ date: 2022-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler