hrr_rb_netconf 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +28 -0
- data/.rspec +3 -0
- data/.travis.yml +32 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE +201 -0
- data/README.md +220 -0
- data/Rakefile +6 -0
- data/demo/server.rb +54 -0
- data/demo/server_over_ssh.rb +97 -0
- data/demo/server_with_session-oriented-database.rb +134 -0
- data/demo/server_with_sessionless-database.rb +81 -0
- data/hrr_rb_netconf.gemspec +28 -0
- data/lib/hrr_rb_netconf.rb +10 -0
- data/lib/hrr_rb_netconf/logger.rb +56 -0
- data/lib/hrr_rb_netconf/server.rb +109 -0
- data/lib/hrr_rb_netconf/server/capabilities.rb +75 -0
- data/lib/hrr_rb_netconf/server/capability.rb +206 -0
- data/lib/hrr_rb_netconf/server/capability/base_1_0.rb +183 -0
- data/lib/hrr_rb_netconf/server/capability/base_1_1.rb +247 -0
- data/lib/hrr_rb_netconf/server/capability/candidate_1_0.rb +34 -0
- data/lib/hrr_rb_netconf/server/capability/confirmed_commit_1_0.rb +24 -0
- data/lib/hrr_rb_netconf/server/capability/confirmed_commit_1_1.rb +24 -0
- data/lib/hrr_rb_netconf/server/capability/rollback_on_error_1_0.rb +16 -0
- data/lib/hrr_rb_netconf/server/capability/startup_1_0.rb +22 -0
- data/lib/hrr_rb_netconf/server/capability/url_1_0.rb +23 -0
- data/lib/hrr_rb_netconf/server/capability/validate_1_0.rb +25 -0
- data/lib/hrr_rb_netconf/server/capability/validate_1_1.rb +25 -0
- data/lib/hrr_rb_netconf/server/capability/writable_running_1_0.rb +17 -0
- data/lib/hrr_rb_netconf/server/capability/xpath_1_0.rb +14 -0
- data/lib/hrr_rb_netconf/server/datastore.rb +30 -0
- data/lib/hrr_rb_netconf/server/datastore/oper_handler.rb +29 -0
- data/lib/hrr_rb_netconf/server/datastore/session.rb +52 -0
- data/lib/hrr_rb_netconf/server/error.rb +52 -0
- data/lib/hrr_rb_netconf/server/error/access_denied.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/bad_attribute.rb +20 -0
- data/lib/hrr_rb_netconf/server/error/bad_element.rb +20 -0
- data/lib/hrr_rb_netconf/server/error/data_exists.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/data_missing.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/in_use.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/invalid_value.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/lock_denied.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/malformed_message.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/missing_attribute.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/missing_element.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/operation_failed.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/operation_not_supported.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/partial_operation.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/resource_denied.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/rollback_failed.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/rpc_errorable.rb +138 -0
- data/lib/hrr_rb_netconf/server/error/too_big.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/unknown_attribute.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/unknown_element.rb +19 -0
- data/lib/hrr_rb_netconf/server/error/unknown_namespace.rb +19 -0
- data/lib/hrr_rb_netconf/server/errors.rb +28 -0
- data/lib/hrr_rb_netconf/server/filter.rb +48 -0
- data/lib/hrr_rb_netconf/server/filter/subtree.rb +135 -0
- data/lib/hrr_rb_netconf/server/filter/xpath.rb +59 -0
- data/lib/hrr_rb_netconf/server/model.rb +123 -0
- data/lib/hrr_rb_netconf/server/model/node.rb +19 -0
- data/lib/hrr_rb_netconf/server/operation.rb +92 -0
- data/lib/hrr_rb_netconf/server/session.rb +177 -0
- data/lib/hrr_rb_netconf/version.rb +6 -0
- metadata +149 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'hrr_rb_netconf/server/error/rpc_errorable'
|
5
|
+
|
6
|
+
module HrrRbNetconf
|
7
|
+
class Server
|
8
|
+
class Error
|
9
|
+
class OperationNotSupported < Error
|
10
|
+
include RpcErrorable
|
11
|
+
|
12
|
+
TAG = 'operation-not-supported'
|
13
|
+
TYPE = ['protocol', 'application']
|
14
|
+
SEVERITY = ['error']
|
15
|
+
INFO = []
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'hrr_rb_netconf/server/error/rpc_errorable'
|
5
|
+
|
6
|
+
module HrrRbNetconf
|
7
|
+
class Server
|
8
|
+
class Error
|
9
|
+
class PartialOperation < Error
|
10
|
+
include RpcErrorable
|
11
|
+
|
12
|
+
TAG = 'partial-operation'
|
13
|
+
TYPE = ['application']
|
14
|
+
SEVERITY = ['error']
|
15
|
+
INFO = ['ok-element', 'err-element', 'noop-element']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'hrr_rb_netconf/server/error/rpc_errorable'
|
5
|
+
|
6
|
+
module HrrRbNetconf
|
7
|
+
class Server
|
8
|
+
class Error
|
9
|
+
class ResourceDenied < Error
|
10
|
+
include RpcErrorable
|
11
|
+
|
12
|
+
TAG = 'resource-denied'
|
13
|
+
TYPE = ['transport', 'rpc', 'protocol', 'application']
|
14
|
+
SEVERITY = ['error']
|
15
|
+
INFO = []
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'hrr_rb_netconf/server/error/rpc_errorable'
|
5
|
+
|
6
|
+
module HrrRbNetconf
|
7
|
+
class Server
|
8
|
+
class Error
|
9
|
+
class RollbackFailed < Error
|
10
|
+
include RpcErrorable
|
11
|
+
|
12
|
+
TAG = 'rollback-failed'
|
13
|
+
TYPE = ['protocol', 'application']
|
14
|
+
SEVERITY = ['error']
|
15
|
+
INFO = []
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'rexml/document'
|
5
|
+
|
6
|
+
module HrrRbNetconf
|
7
|
+
class Server
|
8
|
+
class Error < StandardError
|
9
|
+
module RpcErrorable
|
10
|
+
def initialize type, severity, info: nil, app_tag: nil, path: nil, message: nil
|
11
|
+
@logger = Logger.new self.class.name
|
12
|
+
|
13
|
+
@tag = self.class::TAG
|
14
|
+
@type = type
|
15
|
+
@severity = severity
|
16
|
+
@info = info
|
17
|
+
@app_tag = app_tag
|
18
|
+
@path = path
|
19
|
+
@message = message
|
20
|
+
|
21
|
+
validate
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate
|
25
|
+
validate_type
|
26
|
+
validate_severity
|
27
|
+
validate_info
|
28
|
+
validate_app_tag
|
29
|
+
validate_path
|
30
|
+
validate_message
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_type
|
34
|
+
unless self.class::TYPE.include? @type
|
35
|
+
raise ArgumentError.new "error-type arg must be one of #{self.class::TYPE}, but given #{@type}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def validate_severity
|
40
|
+
unless self.class::SEVERITY.include? @severity
|
41
|
+
raise ArgumentError.new "error-severity arg must be one of #{self.class::SEVERITY}, but given #{@severity}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_info
|
46
|
+
unless self.class::INFO.empty?
|
47
|
+
unless @info.kind_of? Hash
|
48
|
+
raise ArgumentError.new "error-info arg must be a kind of Hash, but given #{@info.class}"
|
49
|
+
end
|
50
|
+
unless self.class::INFO.all?{ |e| @info[e] }
|
51
|
+
raise ArgumentError.new "error-info arg must contain #{self.class::INFO} as keys, but given #{@info}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate_app_tag
|
57
|
+
# Pass
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_path
|
61
|
+
if @path
|
62
|
+
case @path
|
63
|
+
when Hash
|
64
|
+
unless @path['value']
|
65
|
+
raise ArgumentError.new "error-path arg must contain 'value' key if Hash"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def validate_message
|
72
|
+
if @message
|
73
|
+
case @message
|
74
|
+
when Hash
|
75
|
+
unless @message['value']
|
76
|
+
raise ArgumentError.new "error-message arg must contain \"value\" key if Hash"
|
77
|
+
end
|
78
|
+
unless @message.fetch('attributes', {}).keys.include?('xml:lang')
|
79
|
+
@logger.warn { "error-message arg does not contain \"xml:lang\" attribute, so assuming \"en\"" }
|
80
|
+
end
|
81
|
+
else
|
82
|
+
@logger.warn { "error-message arg does not contain \"xml:lang\" attribute, so assuming \"en\"" }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_rpc_error
|
88
|
+
xml_doc = REXML::Document.new
|
89
|
+
rpc_error_e = xml_doc.add_element 'rpc-error'
|
90
|
+
tag_e = rpc_error_e.add_element 'error-tag'
|
91
|
+
tag_e.text = @tag
|
92
|
+
type_e = rpc_error_e.add_element 'error-type'
|
93
|
+
type_e.text = @type
|
94
|
+
severity_e = rpc_error_e.add_element 'error-severity'
|
95
|
+
severity_e.text = @severity
|
96
|
+
if @info
|
97
|
+
info_e = rpc_error_e.add_element 'error-info'
|
98
|
+
case @info
|
99
|
+
when Hash
|
100
|
+
@info.each{ |k, v|
|
101
|
+
child_e = info_e.add_element k
|
102
|
+
child_e.text = v
|
103
|
+
}
|
104
|
+
else
|
105
|
+
info_e.text = @info
|
106
|
+
end
|
107
|
+
end
|
108
|
+
if @app_tag
|
109
|
+
app_tag_e = rpc_error_e.add_element 'error-app-tag'
|
110
|
+
app_tag_e.text = @app_tag
|
111
|
+
end
|
112
|
+
if @path
|
113
|
+
path_e = rpc_error_e.add_element 'error-path'
|
114
|
+
case @path
|
115
|
+
when Hash
|
116
|
+
path_e.add_attributes @path['attributes']
|
117
|
+
path_e.text = @path['value']
|
118
|
+
else
|
119
|
+
path_e.text = @path
|
120
|
+
end
|
121
|
+
end
|
122
|
+
if @message
|
123
|
+
message_e = rpc_error_e.add_element 'error-message'
|
124
|
+
message_e.add_attribute 'xml:lang', 'en'
|
125
|
+
case @message
|
126
|
+
when Hash
|
127
|
+
message_e.add_attributes @message['attributes']
|
128
|
+
message_e.text = @message['value']
|
129
|
+
else
|
130
|
+
message_e.text = @message
|
131
|
+
end
|
132
|
+
end
|
133
|
+
xml_doc.root
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'hrr_rb_netconf/server/error/rpc_errorable'
|
5
|
+
|
6
|
+
module HrrRbNetconf
|
7
|
+
class Server
|
8
|
+
class Error
|
9
|
+
class TooBig < Error
|
10
|
+
include RpcErrorable
|
11
|
+
|
12
|
+
TAG = 'too-big'
|
13
|
+
TYPE = ['transport', 'rpc', 'protocol', 'application']
|
14
|
+
SEVERITY = ['error']
|
15
|
+
INFO = []
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'hrr_rb_netconf/server/error/rpc_errorable'
|
5
|
+
|
6
|
+
module HrrRbNetconf
|
7
|
+
class Server
|
8
|
+
class Error
|
9
|
+
class UnknownAttribute < Error
|
10
|
+
include RpcErrorable
|
11
|
+
|
12
|
+
TAG = 'unknown-attribute'
|
13
|
+
TYPE = ['rpc', 'protocol', 'application']
|
14
|
+
SEVERITY = ['error']
|
15
|
+
INFO = ['bad-attribute', 'bad-element']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'hrr_rb_netconf/server/error/rpc_errorable'
|
5
|
+
|
6
|
+
module HrrRbNetconf
|
7
|
+
class Server
|
8
|
+
class Error
|
9
|
+
class UnknownElement < Error
|
10
|
+
include RpcErrorable
|
11
|
+
|
12
|
+
TAG = 'unknown-element'
|
13
|
+
TYPE = ['protocol', 'application']
|
14
|
+
SEVERITY = ['error']
|
15
|
+
INFO = ['bad-element']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'hrr_rb_netconf/server/error/rpc_errorable'
|
5
|
+
|
6
|
+
module HrrRbNetconf
|
7
|
+
class Server
|
8
|
+
class Error
|
9
|
+
class UnknownNamespace < Error
|
10
|
+
include RpcErrorable
|
11
|
+
|
12
|
+
TAG = 'unknown-namespace'
|
13
|
+
TYPE = ['protocol', 'application']
|
14
|
+
SEVERITY = ['error']
|
15
|
+
INFO = ['bad-element', 'bad-namespace']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'hrr_rb_netconf/server/error'
|
5
|
+
|
6
|
+
module HrrRbNetconf
|
7
|
+
class Server
|
8
|
+
class Errors < StandardError
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
def initialize *errors
|
12
|
+
@errors = errors.flatten
|
13
|
+
validate_errors
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate_errors
|
17
|
+
unless @errors.all?{ |e| e.kind_of? HrrRbNetconf::Server::Error }
|
18
|
+
given = @errors.reject{ |e| e.kind_of? HrrRbNetconf::Server::Error }.map{ |e| e.class }
|
19
|
+
raise ArgumentError.new "Wrong argument type: given #{given}, expected HrrRbNetconf::Server::Error"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def each &blk
|
24
|
+
@errors.each &blk
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
module HrrRbNetconf
|
5
|
+
class Server
|
6
|
+
class Filter
|
7
|
+
@subclass_list = Array.new
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def inherited klass
|
11
|
+
@subclass_list.push klass if @subclass_list
|
12
|
+
end
|
13
|
+
|
14
|
+
def [] key
|
15
|
+
__subclass_list__(__method__).find{ |klass| klass::TYPE == key }
|
16
|
+
end
|
17
|
+
|
18
|
+
def list
|
19
|
+
__subclass_list__(__method__).map{ |klass| klass::TYPE }
|
20
|
+
end
|
21
|
+
|
22
|
+
def __subclass_list__ method_name
|
23
|
+
send(:method_missing, method_name) unless @subclass_list
|
24
|
+
@subclass_list
|
25
|
+
end
|
26
|
+
|
27
|
+
def filter raw_output_e, input_e
|
28
|
+
filter_e = input_e.elements['filter']
|
29
|
+
if filter_e
|
30
|
+
filter_type = filter_e.attributes['type']
|
31
|
+
if self[filter_type]
|
32
|
+
self[filter_type].filter raw_output_e, filter_e
|
33
|
+
else
|
34
|
+
raise Error['bad-attribute'].new('protocol', 'error', info: {'bad-attribute' => filter_type, 'bad-element' => 'filter'})
|
35
|
+
end
|
36
|
+
else
|
37
|
+
raw_output_e
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private :__subclass_list__
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
require 'hrr_rb_netconf/server/filter/subtree'
|
48
|
+
require 'hrr_rb_netconf/server/filter/xpath'
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'rexml/document'
|
5
|
+
|
6
|
+
module HrrRbNetconf
|
7
|
+
class Server
|
8
|
+
class Filter
|
9
|
+
class Subtree < Filter
|
10
|
+
TYPE = 'subtree'
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def filter raw_output_e, filter_e
|
14
|
+
selected_element_xpaths = []
|
15
|
+
output_xml_doc = REXML::Document.new
|
16
|
+
subtree_e = filter_e.elements[1]
|
17
|
+
filter_recursively(selected_element_xpaths, output_xml_doc, raw_output_e, subtree_e)
|
18
|
+
output_xml_doc.root
|
19
|
+
end
|
20
|
+
|
21
|
+
def content_match_nodes_match_all? content_match_nodes, raw_output_e
|
22
|
+
content_match_nodes.all?{ |child_filter_e|
|
23
|
+
child_filter_attributes = child_filter_e.attributes.to_a.reject{ |attr| (attr.prefix =='' && attr.name == 'xmlns') || attr.prefix == 'xmlns' }
|
24
|
+
raw_output_e.elements.to_a.any?{ |child_raw_output_e|
|
25
|
+
(child_filter_e.namespace == "" || child_filter_e.namespace == child_raw_output_e.namespace) && child_filter_e.name == child_raw_output_e.name && child_filter_e.text == child_raw_output_e.text && (
|
26
|
+
child_filter_attributes.empty? || child_filter_attributes.reject{ |child_filter_attr|
|
27
|
+
child_raw_output_e.attributes.to_a.reject{ |attr| (attr.prefix =='' && attr.name == 'xmlns') || attr.prefix == 'xmlns' }.any?{ |child_raw_output_attr|
|
28
|
+
(child_filter_attr.namespace == "" || child_filter_attr.namespace == child_raw_output_attr.namespace) && child_filter_attr.name == child_raw_output_attr.name && child_filter_attr.value == child_raw_output_attr.value
|
29
|
+
}
|
30
|
+
}
|
31
|
+
)
|
32
|
+
}
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_elem selected_element_xpaths, output_e, raw_output_e, output_e_duplicated
|
37
|
+
if output_e_duplicated
|
38
|
+
xpath, elem = selected_element_xpaths.find{ |xpath, elem| xpath == raw_output_e.xpath }
|
39
|
+
unless xpath
|
40
|
+
child_output_e = output_e.add raw_output_e.clone
|
41
|
+
selected_element_xpaths.push [raw_output_e.xpath, child_output_e]
|
42
|
+
[child_output_e, false]
|
43
|
+
else
|
44
|
+
[elem, true]
|
45
|
+
end
|
46
|
+
else
|
47
|
+
child_output_e = output_e.add raw_output_e.clone
|
48
|
+
selected_element_xpaths.push [raw_output_e.xpath, child_output_e]
|
49
|
+
[child_output_e, false]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def filter_recursively selected_element_xpaths, output_e, raw_output_e, filter_e, options={}
|
54
|
+
if filter_e
|
55
|
+
if raw_output_e.name == filter_e.name
|
56
|
+
# Namespace Selection
|
57
|
+
filter_namespace = options['namespace'] || filter_e.namespace
|
58
|
+
if filter_namespace == nil || filter_namespace == "" || raw_output_e.namespace == filter_namespace
|
59
|
+
# Attribute Match Expressions
|
60
|
+
filter_attributes = filter_e.attributes.to_a.reject{ |attr| (attr.prefix =='' && attr.name == 'xmlns') || attr.prefix == 'xmlns' }
|
61
|
+
if filter_attributes.empty? || filter_attributes.reject{ |filter_attr|
|
62
|
+
raw_output_e.attributes.to_a.reject{ |attr| (attr.prefix =='' && attr.name == 'xmlns') || attr.prefix == 'xmlns' }.any?{ |raw_output_attr|
|
63
|
+
filter_attr.namespace == raw_output_attr.namespace && filter_attr.name == raw_output_attr.name && filter_attr.value == raw_output_attr.value
|
64
|
+
}
|
65
|
+
}.empty?
|
66
|
+
if filter_e.has_elements?
|
67
|
+
# Containment Nodes
|
68
|
+
if filter_e.elements.to_a.select{ |c| c.has_text? }.empty?
|
69
|
+
child_output_e, child_output_e_duplicated = add_elem selected_element_xpaths, output_e, raw_output_e, options['output_e_duplicated']
|
70
|
+
raw_output_e.each_element{ |child_raw_output_e|
|
71
|
+
filter_e.elements.to_a.select{ |c| c.name == child_raw_output_e.name && (c.namespace == "" || c.namespace == child_raw_output_e.namespace) }.each{ |child_filter_e|
|
72
|
+
unless child_output_e_duplicated
|
73
|
+
if selected_element_xpaths.any?{ |xpath, elem| xpath == child_raw_output_e.xpath }
|
74
|
+
child_output_e_duplicated = true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
filter_recursively selected_element_xpaths, child_output_e, child_raw_output_e, child_filter_e, {'namespace' => filter_namespace, 'output_e_duplicated' => child_output_e_duplicated}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
# Content Match Nodes
|
81
|
+
else
|
82
|
+
content_match_nodes = filter_e.elements.to_a.select{ |c| c.has_text? }
|
83
|
+
not_content_match_nodes = filter_e.elements.to_a.reject{ |c| c.has_text? }
|
84
|
+
if content_match_nodes_match_all? content_match_nodes, raw_output_e
|
85
|
+
child_output_e, child_output_e_duplicated = add_elem selected_element_xpaths, output_e, raw_output_e, options['output_e_duplicated']
|
86
|
+
if not_content_match_nodes.empty?
|
87
|
+
raw_output_e.each_element{ |child_raw_output_e|
|
88
|
+
child_filter_e = filter_e.elements.to_a.find{ |c| (c.namespace == "" || child_raw_output_e.namespace == c.namespace) && child_raw_output_e.name == c.name }
|
89
|
+
if child_filter_e
|
90
|
+
filter_recursively selected_element_xpaths, child_output_e, child_raw_output_e, child_filter_e, {'namespace' => filter_namespace, 'output_e_duplicated' => child_output_e_duplicated}
|
91
|
+
else
|
92
|
+
filter_recursively selected_element_xpaths, child_output_e, child_raw_output_e, child_filter_e, {'namespace' => filter_namespace, 'in_filter' => true, 'output_e_duplicated' => child_output_e_duplicated}
|
93
|
+
end
|
94
|
+
}
|
95
|
+
else
|
96
|
+
raw_output_e.each_element{ |child_raw_output_e|
|
97
|
+
child_filter_e = filter_e.elements.to_a.find{ |c| (c.namespace == "" || child_raw_output_e.namespace == c.namespace) && child_raw_output_e.name == c.name }
|
98
|
+
filter_recursively selected_element_xpaths, child_output_e, child_raw_output_e, child_filter_e, {'namespace' => filter_namespace, 'output_e_duplicated' => child_output_e_duplicated}
|
99
|
+
}
|
100
|
+
end
|
101
|
+
else
|
102
|
+
end
|
103
|
+
end
|
104
|
+
else
|
105
|
+
child_output_e, child_output_e_duplicated = add_elem selected_element_xpaths, output_e, raw_output_e, options['output_e_duplicated']
|
106
|
+
if raw_output_e.has_text?
|
107
|
+
child_output_e.text = raw_output_e.text
|
108
|
+
else
|
109
|
+
raw_output_e.each_element{ |child_raw_output_e|
|
110
|
+
filter_recursively selected_element_xpaths, child_output_e, child_raw_output_e, nil, {'namespace' => filter_namespace, 'in_filter' => true, 'output_e_duplicated' => child_output_e_duplicated}
|
111
|
+
}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
elsif options['in_filter']
|
118
|
+
# Namespace Selection
|
119
|
+
filter_namespace = options['namespace']
|
120
|
+
if filter_namespace == nil || filter_namespace == "" || raw_output_e.namespace == filter_namespace
|
121
|
+
child_output_e, child_output_e_duplicated = add_elem selected_element_xpaths, output_e, raw_output_e, options['output_e_duplicated']
|
122
|
+
if raw_output_e.has_text?
|
123
|
+
child_output_e.text = raw_output_e.text
|
124
|
+
end
|
125
|
+
raw_output_e.each_element{ |child_raw_output_e|
|
126
|
+
filter_recursively selected_element_xpaths, child_output_e, child_raw_output_e, filter_e, {'namespace' => filter_namespace, 'in_filter' => true, 'outout_e_duplicated' => child_output_e_duplicated}
|
127
|
+
}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|