moxml 0.1.3 → 0.1.4
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 +4 -4
- data/.rubocop_todo.yml +48 -20
- data/Gemfile +1 -0
- data/LICENSE.md +33 -0
- data/README.adoc +32 -10
- data/lib/moxml/adapter/base.rb +12 -0
- data/lib/moxml/adapter/customized_rexml/formatter.rb +195 -0
- data/lib/moxml/adapter/nokogiri.rb +1 -1
- data/lib/moxml/adapter/oga.rb +21 -7
- data/lib/moxml/adapter/rexml.rb +458 -0
- data/lib/moxml/adapter.rb +1 -1
- data/lib/moxml/attribute.rb +2 -2
- data/lib/moxml/config.rb +1 -1
- data/lib/moxml/document_builder.rb +13 -17
- data/lib/moxml/element.rb +2 -2
- data/lib/moxml/namespace.rb +1 -1
- data/lib/moxml/version.rb +1 -1
- data/spec/moxml/adapter/rexml_spec.rb +14 -0
- data/spec/moxml/all_with_adapters_spec.rb +0 -2
- data/spec/support/shared_examples/declaration.rb +1 -0
- data/spec/support/shared_examples/edge_cases.rb +3 -3
- data/spec/support/shared_examples/element.rb +1 -1
- data/spec/support/shared_examples/integration.rb +2 -2
- data/spec/support/shared_examples/xml_adapter.rb +169 -7
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65fadaecfecbc8142d11c82c79c20ea9811e3b58e21b94f335ba822bdfbfc852
|
4
|
+
data.tar.gz: e0189194a594ff763ffec269d15e56dadf91b22369d2efb399e29e3c993f1ace
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c20b0290ed6a6f9ea904564b7619c05f1aec9b9ebe9274a6ea042b9756caeb8792a4d6f45224af8019e2760b8d752ff20a9ef9c4f8f4acb893be069b7f95a92
|
7
|
+
data.tar.gz: 05d046559db87598410f122e51fa7a2276d975f40eabe19f32c65de6c2459238976551496937e33a2a319e3a7ff110bdc782af8ce9942bfcc24840f292d79150
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2025-
|
3
|
+
# on 2025-05-09 11:52:41 UTC using RuboCop version 1.68.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
@@ -17,39 +17,45 @@ Lint/MissingCopEnableDirective:
|
|
17
17
|
Exclude:
|
18
18
|
- 'lib/moxml/adapter/customized_oga/xml_generator.rb'
|
19
19
|
|
20
|
-
# Offense count:
|
20
|
+
# Offense count: 2
|
21
21
|
# Configuration parameters: AllowedParentClasses.
|
22
22
|
Lint/MissingSuper:
|
23
23
|
Exclude:
|
24
24
|
- 'lib/moxml/adapter/customized_oga/xml_declaration.rb'
|
25
|
+
- 'lib/moxml/adapter/customized_rexml/formatter.rb'
|
25
26
|
|
26
|
-
# Offense count:
|
27
|
+
# Offense count: 8
|
27
28
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
28
29
|
Metrics/AbcSize:
|
29
|
-
Max:
|
30
|
+
Max: 39
|
30
31
|
|
31
|
-
# Offense count:
|
32
|
+
# Offense count: 53
|
32
33
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
33
34
|
# AllowedMethods: refine
|
34
35
|
Metrics/BlockLength:
|
35
|
-
Max:
|
36
|
+
Max: 270
|
36
37
|
|
37
|
-
# Offense count:
|
38
|
+
# Offense count: 5
|
38
39
|
# Configuration parameters: CountComments, CountAsOne.
|
39
40
|
Metrics/ClassLength:
|
40
|
-
Max:
|
41
|
+
Max: 335
|
41
42
|
|
42
|
-
# Offense count:
|
43
|
+
# Offense count: 7
|
43
44
|
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
44
45
|
Metrics/CyclomaticComplexity:
|
45
|
-
Max:
|
46
|
+
Max: 15
|
46
47
|
|
47
|
-
# Offense count:
|
48
|
+
# Offense count: 15
|
48
49
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
49
50
|
Metrics/MethodLength:
|
50
|
-
Max:
|
51
|
+
Max: 23
|
51
52
|
|
52
|
-
# Offense count:
|
53
|
+
# Offense count: 3
|
54
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
55
|
+
Metrics/PerceivedComplexity:
|
56
|
+
Max: 15
|
57
|
+
|
58
|
+
# Offense count: 5
|
53
59
|
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
54
60
|
# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
|
55
61
|
Naming/MethodParameterName:
|
@@ -57,17 +63,39 @@ Naming/MethodParameterName:
|
|
57
63
|
- 'lib/moxml/adapter/customized_oga/xml_generator.rb'
|
58
64
|
- 'lib/moxml/adapter/nokogiri.rb'
|
59
65
|
- 'lib/moxml/adapter/ox.rb'
|
66
|
+
- 'lib/moxml/adapter/rexml.rb'
|
60
67
|
- 'lib/moxml/attribute.rb'
|
61
68
|
|
62
|
-
# Offense count:
|
69
|
+
# Offense count: 1
|
70
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
71
|
+
Style/CombinableLoops:
|
72
|
+
Exclude:
|
73
|
+
- 'lib/moxml/adapter/customized_rexml/formatter.rb'
|
74
|
+
|
75
|
+
# Offense count: 28
|
63
76
|
# Configuration parameters: AllowedConstants.
|
64
77
|
Style/Documentation:
|
65
78
|
Enabled: false
|
66
79
|
|
67
|
-
# Offense count:
|
68
|
-
# This cop supports
|
69
|
-
# Configuration parameters: EnforcedStyle
|
70
|
-
# SupportedStyles:
|
71
|
-
Style/
|
80
|
+
# Offense count: 1
|
81
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
82
|
+
# Configuration parameters: EnforcedStyle.
|
83
|
+
# SupportedStyles: always, always_true, never
|
84
|
+
Style/FrozenStringLiteralComment:
|
85
|
+
Exclude:
|
86
|
+
- 'lib/moxml/adapter/customized_rexml/formatter.rb'
|
87
|
+
|
88
|
+
# Offense count: 2
|
89
|
+
# Configuration parameters: MinBranchesCount.
|
90
|
+
Style/HashLikeCase:
|
91
|
+
Exclude:
|
92
|
+
- 'lib/moxml/adapter/customized_rexml/formatter.rb'
|
93
|
+
|
94
|
+
# Offense count: 2
|
95
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
96
|
+
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
|
97
|
+
# AllowedMethods: present?, blank?, presence, try, try!
|
98
|
+
Style/SafeNavigation:
|
72
99
|
Exclude:
|
73
|
-
- '
|
100
|
+
- 'lib/moxml/adapter/customized_rexml/formatter.rb'
|
101
|
+
- 'lib/moxml/adapter/rexml.rb'
|
data/Gemfile
CHANGED
data/LICENSE.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
Licenses & Copyright
|
2
|
+
====================
|
3
|
+
|
4
|
+
This license file adheres to the formatting guidelines of
|
5
|
+
[readable-licenses](https://github.com/nevir/readable-licenses).
|
6
|
+
|
7
|
+
|
8
|
+
Ribose's BSD 2-Clause License
|
9
|
+
-----------------------------
|
10
|
+
|
11
|
+
Copyright (c) 2024, [Ribose Inc](https://www.ribose.com).
|
12
|
+
All rights reserved.
|
13
|
+
|
14
|
+
Redistribution and use in source and binary forms, with or without modification,
|
15
|
+
are permitted provided that the following conditions are met:
|
16
|
+
|
17
|
+
1. Redistributions of source code must retain the above copyright notice,
|
18
|
+
this list of conditions and the following disclaimer.
|
19
|
+
|
20
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
21
|
+
this list of conditions and the following disclaimer in the documentation
|
22
|
+
and/or other materials provided with the distribution.
|
23
|
+
|
24
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
25
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
26
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
27
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
28
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
29
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
30
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
31
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
32
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
33
|
+
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.adoc
CHANGED
@@ -24,15 +24,35 @@ Key features:
|
|
24
24
|
* Easy switching between XML processing engines
|
25
25
|
* Clean separation between interface and implementation
|
26
26
|
|
27
|
+
== Supported XML libraries
|
28
|
+
|
29
|
+
Moxml supports the following XML libraries:
|
30
|
+
|
31
|
+
REXML:: (default) https://github.com/ruby/rexml[REXML], a pure Ruby XML parser
|
32
|
+
distributed with standard Ruby. Not the fastest, but always available.
|
33
|
+
|
34
|
+
Nokogiri:: (recommended) https://github.com/sparklemotion/nokogiri[Nokogiri], a
|
35
|
+
widely used implementation which wraps around the performant
|
36
|
+
https://github.com/GNOME/libxml2[libxml2] C library.
|
37
|
+
|
38
|
+
Oga:: https://github.com/yorickpeterse/oga[Oga], a pure Ruby XML parser.
|
39
|
+
Recommended when you need a pure Ruby solution say for
|
40
|
+
https://github.com/opal/opal[Opal].
|
41
|
+
|
42
|
+
Ox:: https://github.com/ohler55/ox[Ox], a fast XML parser (to be supported)
|
43
|
+
|
44
|
+
|
27
45
|
== Getting started
|
28
46
|
|
47
|
+
=== Installation
|
48
|
+
|
29
49
|
Install the gem and at least one supported XML library:
|
30
50
|
|
31
51
|
[source,ruby]
|
32
52
|
----
|
33
53
|
# In your Gemfile
|
34
54
|
gem 'moxml'
|
35
|
-
gem 'nokogiri' # Or 'oga', or 'ox' when it is integrated
|
55
|
+
gem 'nokogiri' # Or 'oga', 'rexml', or 'ox' when it is integrated
|
36
56
|
----
|
37
57
|
|
38
58
|
=== Basic document creation
|
@@ -478,22 +498,23 @@ end
|
|
478
498
|
|
479
499
|
=== Default adapter selection
|
480
500
|
|
481
|
-
To
|
482
|
-
|
501
|
+
To select a non-default adapter, set it before processing any input using the
|
502
|
+
following syntax.
|
483
503
|
|
484
504
|
[source,ruby]
|
485
505
|
----
|
486
506
|
Moxml::Config.default_adapter = <adapter-symbol>
|
487
507
|
----
|
488
508
|
|
489
|
-
|
509
|
+
Where, `<adapter-symbol>` is one of the following:
|
510
|
+
|
511
|
+
`:rexml`:: REXML (default)
|
490
512
|
|
491
|
-
`:nokogiri`::
|
492
|
-
wrapper around the https://github.com/GNOME/libxml2[libxml2] C library
|
513
|
+
`:nokogiri`:: Nokogiri
|
493
514
|
|
494
|
-
`:oga`::
|
515
|
+
`:oga`:: Oga
|
495
516
|
|
496
|
-
`:ox`::
|
517
|
+
`:ox`:: Ox (not yet supported)
|
497
518
|
|
498
519
|
|
499
520
|
== Thread safety
|
@@ -597,7 +618,8 @@ end
|
|
597
618
|
|
598
619
|
== License
|
599
620
|
|
600
|
-
Copyright (c)
|
621
|
+
Copyright (c) Ribose Inc.
|
601
622
|
|
602
|
-
This project is licensed under the BSD-2-Clause License. See the
|
623
|
+
This project is licensed under the BSD-2-Clause License. See the
|
624
|
+
link:LICENSE.md[] file for details.
|
603
625
|
|
data/lib/moxml/adapter/base.rb
CHANGED
@@ -63,6 +63,18 @@ module Moxml
|
|
63
63
|
create_native_namespace(element, prefix, uri)
|
64
64
|
end
|
65
65
|
|
66
|
+
def set_attribute_name(attribute, name)
|
67
|
+
attribute.name = name
|
68
|
+
end
|
69
|
+
|
70
|
+
def set_attribute_value(attribute, value)
|
71
|
+
attribute.value = value
|
72
|
+
end
|
73
|
+
|
74
|
+
def duplicate_node(node)
|
75
|
+
node.dup
|
76
|
+
end
|
77
|
+
|
66
78
|
protected
|
67
79
|
|
68
80
|
def create_native_element(name)
|
@@ -0,0 +1,195 @@
|
|
1
|
+
require "rexml/formatters/pretty"
|
2
|
+
|
3
|
+
module Moxml
|
4
|
+
module Adapter
|
5
|
+
module CustomizedRexml
|
6
|
+
# Custom REXML formatter that fixes indentation and wrapping issues
|
7
|
+
class Formatter < ::REXML::Formatters::Pretty
|
8
|
+
def initialize(indentation: 2, self_close_empty: false)
|
9
|
+
@indentation = " " * indentation
|
10
|
+
@level = 0
|
11
|
+
@compact = true
|
12
|
+
@width = -1 # Disable line wrapping
|
13
|
+
@self_close_empty = self_close_empty
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(node, output)
|
17
|
+
case node
|
18
|
+
when ::REXML::XMLDecl
|
19
|
+
write_declaration(node, output)
|
20
|
+
else
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def write_element(node, output)
|
26
|
+
# output << ' ' * @level
|
27
|
+
output << "<#{node.expanded_name}"
|
28
|
+
write_attributes(node, output)
|
29
|
+
|
30
|
+
if node.children.empty? && @self_close_empty
|
31
|
+
output << "/>"
|
32
|
+
return
|
33
|
+
end
|
34
|
+
|
35
|
+
output << ">"
|
36
|
+
|
37
|
+
# Check for mixed content
|
38
|
+
has_text = node.children.any? { |c| c.is_a?(::REXML::Text) && !c.to_s.strip.empty? }
|
39
|
+
has_elements = node.children.any? { |c| c.is_a?(::REXML::Element) }
|
40
|
+
mixed = has_text && has_elements
|
41
|
+
|
42
|
+
# Handle children based on content type
|
43
|
+
unless node.children.empty?
|
44
|
+
@level += @indentation.length unless mixed
|
45
|
+
|
46
|
+
node.children.each_with_index do |child, _index|
|
47
|
+
# Skip insignificant whitespace
|
48
|
+
next if child.is_a?(::REXML::Text) &&
|
49
|
+
child.to_s.strip.empty? &&
|
50
|
+
!(child.next_sibling.nil? && child.previous_sibling.nil?)
|
51
|
+
|
52
|
+
# Indent non-text nodes in non-mixed content
|
53
|
+
# if !mixed && !child.is_a?(::REXML::Text)
|
54
|
+
# output << ' ' * @level
|
55
|
+
# end
|
56
|
+
|
57
|
+
write(child, output)
|
58
|
+
|
59
|
+
# Add newlines between elements in non-mixed content
|
60
|
+
# if !mixed && !child.is_a?(::REXML::Text) && index < node.children.size - 1
|
61
|
+
# output << "\n"
|
62
|
+
# end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Reset indentation for closing tag in non-mixed content
|
66
|
+
unless mixed
|
67
|
+
@level -= @indentation.length
|
68
|
+
# output << ' ' * @level
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
output << "</#{node.expanded_name}>"
|
73
|
+
# output << "\n" unless mixed
|
74
|
+
end
|
75
|
+
|
76
|
+
def write_text(node, output)
|
77
|
+
text = node.value
|
78
|
+
return if text.empty?
|
79
|
+
|
80
|
+
output << escape_text(text)
|
81
|
+
end
|
82
|
+
|
83
|
+
def escape_text(text)
|
84
|
+
text.to_s.gsub(/[<>&]/) do |match|
|
85
|
+
case match
|
86
|
+
when "<" then "<"
|
87
|
+
when ">" then ">"
|
88
|
+
when "&" then "&"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def find_significant_sibling(node, direction)
|
96
|
+
method = direction == :next ? :next_sibling : :previous_sibling
|
97
|
+
sibling = node.send(method)
|
98
|
+
sibling = sibling.send(method) while sibling && sibling.is_a?(::REXML::Text) && sibling.to_s.strip.empty?
|
99
|
+
sibling
|
100
|
+
end
|
101
|
+
|
102
|
+
def write_cdata(node, output)
|
103
|
+
# output << ' ' * @level
|
104
|
+
output << "<![CDATA["
|
105
|
+
output << node.to_s.gsub("]]>", "]]]]><![CDATA[>")
|
106
|
+
output << "]]>"
|
107
|
+
# output << "\n"
|
108
|
+
end
|
109
|
+
|
110
|
+
def write_comment(node, output)
|
111
|
+
# output << ' ' * @level
|
112
|
+
output << "<!--"
|
113
|
+
output << node.to_s
|
114
|
+
output << "-->"
|
115
|
+
# output << "\n"
|
116
|
+
end
|
117
|
+
|
118
|
+
def write_instruction(node, output)
|
119
|
+
# output << ' ' * @level
|
120
|
+
output << "<?"
|
121
|
+
output << node.target
|
122
|
+
output << " "
|
123
|
+
output << node.content if node.content
|
124
|
+
output << "?>"
|
125
|
+
# output << "\n"
|
126
|
+
end
|
127
|
+
|
128
|
+
def write_document(node, output)
|
129
|
+
node.children.each do |child|
|
130
|
+
write(child, output)
|
131
|
+
# output << "\n" unless child == node.children.last
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def write_doctype(node, output)
|
136
|
+
output << "<!DOCTYPE "
|
137
|
+
output << node.name
|
138
|
+
output << " "
|
139
|
+
output << node.external_id if node.external_id
|
140
|
+
output << ">"
|
141
|
+
# output << "\n"
|
142
|
+
end
|
143
|
+
|
144
|
+
def write_declaration(node, output)
|
145
|
+
output << "<?xml"
|
146
|
+
output << %( version="#{node.version}") if node.version
|
147
|
+
output << %( encoding="#{node.encoding.to_s.upcase}") if node.writeencoding
|
148
|
+
output << %( standalone="#{node.standalone}") if node.standalone
|
149
|
+
output << "?>"
|
150
|
+
# output << "\n"
|
151
|
+
end
|
152
|
+
|
153
|
+
def write_attributes(node, output)
|
154
|
+
# First write namespace declarations
|
155
|
+
node.attributes.each do |name, attr|
|
156
|
+
next unless name.to_s.start_with?("xmlns:") || name.to_s == "xmlns"
|
157
|
+
|
158
|
+
name = "xmlns" if name.to_s == "xmlns:" # convert the default namespace
|
159
|
+
value = attr.respond_to?(:value) ? attr.value : attr
|
160
|
+
output << " #{name}=\"#{value}\""
|
161
|
+
end
|
162
|
+
|
163
|
+
# Then write regular attributes
|
164
|
+
node.attributes.each do |name, attr|
|
165
|
+
next if name.to_s.start_with?("xmlns:") || name.to_s == "xmlns"
|
166
|
+
|
167
|
+
output << " "
|
168
|
+
output << if attr.respond_to?(:prefix) && attr.prefix
|
169
|
+
"#{attr.prefix}:#{attr.name}"
|
170
|
+
else
|
171
|
+
name.to_s
|
172
|
+
end
|
173
|
+
|
174
|
+
output << "=\""
|
175
|
+
value = attr.respond_to?(:value) ? attr.value : attr
|
176
|
+
output << escape_attribute_value(value.to_s)
|
177
|
+
output << "\""
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def escape_attribute_value(value)
|
182
|
+
value.to_s.gsub(/[<>&"]/) do |match|
|
183
|
+
case match
|
184
|
+
when "<" then "<"
|
185
|
+
when ">" then ">"
|
186
|
+
when "&" then "&"
|
187
|
+
when '"' then """
|
188
|
+
# when "'" then '''
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
data/lib/moxml/adapter/oga.rb
CHANGED
@@ -213,11 +213,25 @@ module Moxml
|
|
213
213
|
end
|
214
214
|
|
215
215
|
def add_previous_sibling(node, sibling)
|
216
|
-
node.
|
216
|
+
if node.parent == sibling.parent
|
217
|
+
# Oga doesn't manipulate children of the same parent
|
218
|
+
dup_sibling = node.node_set.delete(sibling)
|
219
|
+
index = node.node_set.index(node)
|
220
|
+
node.node_set.insert(index, dup_sibling)
|
221
|
+
else
|
222
|
+
node.before(sibling)
|
223
|
+
end
|
217
224
|
end
|
218
225
|
|
219
226
|
def add_next_sibling(node, sibling)
|
220
|
-
node.
|
227
|
+
if node.parent == sibling.parent
|
228
|
+
# Oga doesn't manipulate children of the same parent
|
229
|
+
dup_sibling = node.node_set.delete(sibling)
|
230
|
+
index = node.node_set.index(node) + 1
|
231
|
+
node.node_set.insert(index, dup_sibling)
|
232
|
+
else
|
233
|
+
node.after(sibling)
|
234
|
+
end
|
221
235
|
end
|
222
236
|
|
223
237
|
def remove(node)
|
@@ -229,7 +243,7 @@ module Moxml
|
|
229
243
|
end
|
230
244
|
|
231
245
|
def replace_children(node, new_children)
|
232
|
-
node.
|
246
|
+
node.children = []
|
233
247
|
new_children.each { |child| add_child(node, child) }
|
234
248
|
end
|
235
249
|
|
@@ -296,14 +310,14 @@ module Moxml
|
|
296
310
|
node.namespaces.values
|
297
311
|
end
|
298
312
|
|
299
|
-
def xpath(node, expression,
|
300
|
-
node.xpath(expression).to_a
|
313
|
+
def xpath(node, expression, namespaces = nil)
|
314
|
+
node.xpath(expression, {}, namespaces: namespaces&.transform_keys(&:to_s)).to_a
|
301
315
|
rescue ::LL::ParserError => e
|
302
316
|
raise Moxml::XPathError, e.message
|
303
317
|
end
|
304
318
|
|
305
|
-
def at_xpath(node, expression,
|
306
|
-
node.at_xpath(expression)
|
319
|
+
def at_xpath(node, expression, namespaces = nil)
|
320
|
+
node.at_xpath(expression, namespaces: namespaces)
|
307
321
|
rescue ::Oga::XPath::Error => e
|
308
322
|
raise Moxml::XPathError, e.message
|
309
323
|
end
|