moxml 0.1.12 → 0.1.14

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: 4157530fd51f50d52969541f0a41d18f3b70d2ccada5dea86ea38e3882511385
4
- data.tar.gz: ea71910278f9883ac2580e3f20d9d6a5ea2d0981fbbd9d9c7fecbcf6b2694247
3
+ metadata.gz: c46c9d241e38351b1547ab8be8297ff2902886f022ccdfb3fc2f196d2594bf2b
4
+ data.tar.gz: b1d34fb4306d96d940afea932d5d9f6c6bcffc74c6715e00a6f622302be2f878
5
5
  SHA512:
6
- metadata.gz: 47dd22ad3d886d60cd6f4c2717f0d39e78ebbcaa743cb14a072476753410c681fb19b0a6d3fd6019f7a70bb2a7902bbb3239d4255f5fe5041a4fd2dce5beec74
7
- data.tar.gz: fa217b1a960165a88dc97bcf765147d836dbe77e90be528cdb045ed99c28f6181d59634e50a4059348b89f0a23c4661660e1fb10fe8a46e06e1a434f9e08f456
6
+ metadata.gz: 9178c13199c195aa0b3ed628d5837fa6c1fdaeaa3e3cc462a8520a89ad6bb98963ff0a9c2b668038ff27a0653e2aa2fba98ce1c8bc10eccc74abab0daa26e455
7
+ data.tar.gz: 5b1b06dea56ac0b28dd2b8ca072fa554039936c336e6b262430d40f45ab2972b1e6bf38f3c13cf192c9fc2a9cc9fe827abc99aa662d30ebdaae97d361d981475
@@ -61,23 +61,23 @@ module Moxml
61
61
  )
62
62
  end
63
63
 
64
- def create_element(name)
64
+ def create_element(name, owner_doc: nil)
65
65
  validate_element_name(name)
66
- create_native_element(name)
66
+ create_native_element(name, owner_doc)
67
67
  end
68
68
 
69
- def create_text(content)
69
+ def create_text(content, owner_doc: nil)
70
70
  # Ox freezes the content, so we need to dup it
71
- create_native_text(normalize_xml_value(content).dup)
71
+ create_native_text(normalize_xml_value(content).dup, owner_doc)
72
72
  end
73
73
 
74
- def create_cdata(content)
75
- create_native_cdata(normalize_xml_value(content))
74
+ def create_cdata(content, owner_doc: nil)
75
+ create_native_cdata(normalize_xml_value(content), owner_doc)
76
76
  end
77
77
 
78
- def create_comment(content)
78
+ def create_comment(content, owner_doc: nil)
79
79
  validate_comment_content(content)
80
- create_native_comment(normalize_xml_value(content))
80
+ create_native_comment(normalize_xml_value(content), owner_doc)
81
81
  end
82
82
 
83
83
  def create_doctype(name, external_id, system_id)
@@ -146,7 +146,7 @@ module Moxml
146
146
 
147
147
  protected
148
148
 
149
- def create_native_element(_name)
149
+ def create_native_element(_name, _owner_doc = nil)
150
150
  raise Moxml::NotImplementedError.new(
151
151
  "create_native_element not implemented",
152
152
  feature: "create_native_element",
@@ -154,7 +154,7 @@ module Moxml
154
154
  )
155
155
  end
156
156
 
157
- def create_native_text(_content)
157
+ def create_native_text(_content, _owner_doc = nil)
158
158
  raise Moxml::NotImplementedError.new(
159
159
  "create_native_text not implemented",
160
160
  feature: "create_native_text",
@@ -162,7 +162,7 @@ module Moxml
162
162
  )
163
163
  end
164
164
 
165
- def create_native_cdata(_content)
165
+ def create_native_cdata(_content, _owner_doc = nil)
166
166
  raise Moxml::NotImplementedError.new(
167
167
  "create_native_cdata not implemented",
168
168
  feature: "create_native_cdata",
@@ -170,7 +170,7 @@ module Moxml
170
170
  )
171
171
  end
172
172
 
173
- def create_native_comment(_content)
173
+ def create_native_comment(_content, _owner_doc = nil)
174
174
  raise Moxml::NotImplementedError.new(
175
175
  "create_native_comment not implemented",
176
176
  feature: "create_native_comment",
@@ -217,6 +217,14 @@ module Moxml
217
217
  adapter: name,
218
218
  )
219
219
  end
220
+
221
+ def in_scope_namespaces(_element)
222
+ raise Moxml::NotImplementedError.new(
223
+ "in_scope_namespaces not implemented",
224
+ feature: "in_scope_namespaces",
225
+ adapter: name,
226
+ )
227
+ end
220
228
  end
221
229
  end
222
230
  end
@@ -16,7 +16,7 @@ module Moxml
16
16
  def on_element(element, output)
17
17
  name = element.expanded_name
18
18
 
19
- attrs = ""
19
+ attrs = []
20
20
  element.attributes.each do |attr|
21
21
  attrs << " "
22
22
  on_attribute(attr, attrs)
@@ -28,7 +28,7 @@ module Moxml
28
28
  ">"
29
29
  end
30
30
 
31
- output << "<#{name}#{attrs}#{closing_tag}"
31
+ output << "<#{name}#{attrs.join}#{closing_tag}"
32
32
  end
33
33
 
34
34
  def on_namespace_definition(ns, output)
@@ -126,21 +126,21 @@ module Moxml
126
126
  ::LibXML::XML::Document.new
127
127
  end
128
128
 
129
- def create_native_element(name)
129
+ def create_native_element(name, _owner_doc = nil)
130
130
  ::LibXML::XML::Node.new(name.to_s)
131
131
  end
132
132
 
133
- def create_native_text(content)
133
+ def create_native_text(content, _owner_doc = nil)
134
134
  native = ::LibXML::XML::Node.new_text(content.to_s)
135
135
  CustomizedLibxml::Text.new(native)
136
136
  end
137
137
 
138
- def create_native_cdata(content)
138
+ def create_native_cdata(content, _owner_doc = nil)
139
139
  native = ::LibXML::XML::Node.new_cdata(content.to_s)
140
140
  CustomizedLibxml::Cdata.new(native)
141
141
  end
142
142
 
143
- def create_native_comment(content)
143
+ def create_native_comment(content, _owner_doc = nil)
144
144
  native = ::LibXML::XML::Node.new_comment(content.to_s)
145
145
  CustomizedLibxml::Comment.new(native)
146
146
  end
@@ -70,20 +70,20 @@ module Moxml
70
70
  )
71
71
  end
72
72
 
73
- def create_native_element(name)
74
- ::Nokogiri::XML::Element.new(name, create_document)
73
+ def create_native_element(name, owner_doc = nil)
74
+ ::Nokogiri::XML::Element.new(name, owner_doc || create_document)
75
75
  end
76
76
 
77
- def create_native_text(content)
78
- ::Nokogiri::XML::Text.new(content, create_document)
77
+ def create_native_text(content, owner_doc = nil)
78
+ ::Nokogiri::XML::Text.new(content, owner_doc || create_document)
79
79
  end
80
80
 
81
- def create_native_cdata(content)
82
- ::Nokogiri::XML::CDATA.new(create_document, content)
81
+ def create_native_cdata(content, owner_doc = nil)
82
+ ::Nokogiri::XML::CDATA.new(owner_doc || create_document, content)
83
83
  end
84
84
 
85
- def create_native_comment(content)
86
- ::Nokogiri::XML::Comment.new(create_document, content)
85
+ def create_native_comment(content, owner_doc = nil)
86
+ ::Nokogiri::XML::Comment.new(owner_doc || create_document, content)
87
87
  end
88
88
 
89
89
  def create_native_doctype(name, external_id, system_id)
@@ -334,6 +334,10 @@ module Moxml
334
334
  node.namespace_definitions
335
335
  end
336
336
 
337
+ def in_scope_namespaces(element)
338
+ element.namespace_scopes
339
+ end
340
+
337
341
  # Doctype accessor methods
338
342
  def doctype_name(native)
339
343
  native.name
@@ -64,19 +64,19 @@ module Moxml
64
64
  ::Oga::XML::Document.new
65
65
  end
66
66
 
67
- def create_native_element(name)
67
+ def create_native_element(name, _owner_doc = nil)
68
68
  ::Oga::XML::Element.new(name: name)
69
69
  end
70
70
 
71
- def create_native_text(content)
71
+ def create_native_text(content, _owner_doc = nil)
72
72
  ::Oga::XML::Text.new(text: encode_entity_markers(content))
73
73
  end
74
74
 
75
- def create_native_cdata(content)
75
+ def create_native_cdata(content, _owner_doc = nil)
76
76
  ::Oga::XML::Cdata.new(text: content)
77
77
  end
78
78
 
79
- def create_native_comment(content)
79
+ def create_native_comment(content, _owner_doc = nil)
80
80
  ::Oga::XML::Comment.new(text: content)
81
81
  end
82
82
 
@@ -479,7 +479,7 @@ module Moxml
479
479
 
480
480
  if should_include_decl && !node.xml_declaration && !has_existing_declaration
481
481
  # Need to add declaration - create default one
482
- output = +""
482
+ output = []
483
483
  output << '<?xml version="1.0" encoding="UTF-8"?>'
484
484
  output << "\n"
485
485
 
@@ -491,10 +491,10 @@ module Moxml
491
491
  output << ::Moxml::Adapter::CustomizedOga::XmlGenerator.new(child).to_xml
492
492
  end
493
493
 
494
- return output
494
+ return output.join
495
495
  elsif !should_include_decl
496
496
  # Skip xml_declaration
497
- output = +""
497
+ output = []
498
498
 
499
499
  # Serialize doctype if present
500
500
  output << node.doctype.to_xml << "\n" if node.doctype
@@ -506,7 +506,7 @@ module Moxml
506
506
  output << ::Moxml::Adapter::CustomizedOga::XmlGenerator.new(child).to_xml
507
507
  end
508
508
 
509
- return output
509
+ return output.join
510
510
  end
511
511
  end
512
512
 
@@ -514,19 +514,20 @@ module Moxml
514
514
  # But first check if we need to handle declaration specially
515
515
  if node.is_a?(::Oga::XML::Document) && node.xml_declaration
516
516
  # Document has declaration - use custom handling to avoid duplicates
517
- output = +""
517
+ output = []
518
+ xml_declaration_serialized = false
518
519
 
519
520
  # Serialize children, but skip XmlDeclaration if it would cause duplication
520
521
  node.children.each do |child|
521
- # Check if this would cause duplication by seeing if we already have one in output
522
- if child.is_a?(::Oga::XML::XmlDeclaration) && output.include?("<?xml")
523
- next # Skip duplicate declaration
524
- end
522
+ xml_declaration = child.is_a?(::Oga::XML::XmlDeclaration)
523
+ next if xml_declaration && xml_declaration_serialized
524
+
525
+ xml_declaration_serialized = true if xml_declaration
525
526
 
526
527
  output << ::Moxml::Adapter::CustomizedOga::XmlGenerator.new(child).to_xml
527
528
  end
528
529
 
529
- output
530
+ output.join
530
531
  else
531
532
  # Normal case - use XmlGenerator directly
532
533
  ::Moxml::Adapter::CustomizedOga::XmlGenerator.new(node).to_xml
@@ -67,21 +67,21 @@ module Moxml
67
67
  ::Ox::Document.new(**attrs)
68
68
  end
69
69
 
70
- def create_native_element(name)
70
+ def create_native_element(name, _owner_doc = nil)
71
71
  element = ::Ox::Element.new(name)
72
72
  element.instance_variable_set(:@attributes, {})
73
73
  element
74
74
  end
75
75
 
76
- def create_native_text(content)
76
+ def create_native_text(content, _owner_doc = nil)
77
77
  content
78
78
  end
79
79
 
80
- def create_native_cdata(content)
80
+ def create_native_cdata(content, _owner_doc = nil)
81
81
  ::Ox::CData.new(content)
82
82
  end
83
83
 
84
- def create_native_comment(content)
84
+ def create_native_comment(content, _owner_doc = nil)
85
85
  ::Ox::Comment.new(content)
86
86
  end
87
87
 
@@ -69,19 +69,19 @@ module Moxml
69
69
  ::REXML::Document.new
70
70
  end
71
71
 
72
- def create_native_element(name)
72
+ def create_native_element(name, _owner_doc = nil)
73
73
  ::REXML::Element.new(name.to_s)
74
74
  end
75
75
 
76
- def create_native_text(content)
76
+ def create_native_text(content, _owner_doc = nil)
77
77
  ::REXML::Text.new(content.to_s, true, nil)
78
78
  end
79
79
 
80
- def create_native_cdata(content)
80
+ def create_native_cdata(content, _owner_doc = nil)
81
81
  ::REXML::CData.new(content.to_s)
82
82
  end
83
83
 
84
- def create_native_comment(content)
84
+ def create_native_comment(content, _owner_doc = nil)
85
85
  ::REXML::Comment.new(content.to_s)
86
86
  end
87
87
 
@@ -34,19 +34,19 @@ module Moxml
34
34
  end
35
35
 
36
36
  def create_element(name)
37
- Element.new(adapter.create_element(name), context)
37
+ Element.new(adapter.create_element(name, owner_doc: @native), context)
38
38
  end
39
39
 
40
40
  def create_text(content)
41
- Text.new(adapter.create_text(content), context)
41
+ Text.new(adapter.create_text(content, owner_doc: @native), context)
42
42
  end
43
43
 
44
44
  def create_cdata(content)
45
- Cdata.new(adapter.create_cdata(content), context)
45
+ Cdata.new(adapter.create_cdata(content, owner_doc: @native), context)
46
46
  end
47
47
 
48
48
  def create_comment(content)
49
- Comment.new(adapter.create_comment(content), context)
49
+ Comment.new(adapter.create_comment(content, owner_doc: @native), context)
50
50
  end
51
51
 
52
52
  def create_doctype(name, external_id, system_id)
data/lib/moxml/element.rb CHANGED
@@ -117,6 +117,14 @@ module Moxml
117
117
  end
118
118
  alias namespace_definitions namespaces
119
119
 
120
+ # Returns all namespaces in scope for this element,
121
+ # including those inherited from ancestor elements.
122
+ def in_scope_namespaces
123
+ adapter.in_scope_namespaces(@native).map do |ns|
124
+ Namespace.new(ns, context)
125
+ end
126
+ end
127
+
120
128
  # Returns the namespace URI of this element (alias for namespace_uri)
121
129
  def namespace_name
122
130
  namespace_uri
data/lib/moxml/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Moxml
4
- VERSION = "0.1.12"
4
+ VERSION = "0.1.14"
5
5
  end
@@ -12,6 +12,22 @@ RSpec.describe Moxml::Adapter::Oga do
12
12
 
13
13
  it_behaves_like "xml adapter"
14
14
 
15
+ describe "serialization" do
16
+ it "does not duplicate XML declarations when declaration nodes repeat" do
17
+ context = Moxml::Context.new(:oga)
18
+ doc = context.create_document
19
+
20
+ doc.add_child(doc.create_declaration("1.0", "UTF-8"))
21
+ doc.add_child(doc.create_declaration("1.0", "UTF-8"))
22
+ doc.add_child(doc.create_element("root"))
23
+
24
+ serialized = doc.to_xml
25
+
26
+ expect(serialized.scan("<?xml").size).to eq(1)
27
+ expect(serialized).to include("<root></root>")
28
+ end
29
+ end
30
+
15
31
  describe "entity handling" do
16
32
  it "preserves non-breaking space through parse and serialize round-trip" do
17
33
  xml = "<root>Item&nbsp;One</root>"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moxml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.12
4
+ version: 0.1.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-04-16 00:00:00.000000000 Z
11
+ date: 2026-04-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  Moxml is a unified XML manipulation library that provides a common API