moxml 0.5.27 → 0.5.29
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/lib/moxml/adapter/leptris/serialize.rb +10 -4
- data/lib/moxml/adapter/leptris.rb +13 -0
- data/lib/moxml/adapter/oga.rb +6 -0
- data/lib/moxml/adapter/ox.rb +6 -0
- data/lib/moxml/adapter/rexml.rb +8 -0
- data/lib/moxml/version.rb +1 -1
- data/spec/integration/shared_examples/node_wrappers/namespace_behavior.rb +6 -0
- data/spec/moxml/adapter/leptris_spec.rb +19 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: df62f6f6a27c7ff63c2893ae7d85547d09645d059b187fd4235111c18ad2467f
|
|
4
|
+
data.tar.gz: a9c0e9ee0a3f7f2c8775ba5dfa49563e048ef3e2aac506eaef9135c2a2390139
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 705a551074ea195562d7af4b726a388e8c3517ec4366cf9dff3d3b0828a79f46b6a50d79501d9c5ed1df871855f90bc5d5b69b35e22eb006b558e26c0da5626b
|
|
7
|
+
data.tar.gz: 2e5b4b7da9018d41434c23c70ea4ced99e626ef813dc92b6d2e1df8d9f8f81e89ac536dd52f684bd95de9fcb610ba673eaa9914de5048a491ee0f217bdfa1975
|
|
@@ -91,17 +91,23 @@ module Moxml
|
|
|
91
91
|
# reparsing truncates at it. Valid markup NEVER puts "<"
|
|
92
92
|
# before a non-name, non-delimiter character, so this is
|
|
93
93
|
# deterministic in markup segments (CDATA is literal and
|
|
94
|
-
# excluded by the segment walker).
|
|
94
|
+
# excluded by the segment walker). One class-anchored scan:
|
|
95
|
+
# multi-char literal probes cost ~30x a single regex pass on
|
|
96
|
+
# CRuby (measured include?("< ") at 31µs vs this regex at
|
|
97
|
+
# 64µs for 14 probes' worth of coverage on 32KB).
|
|
95
98
|
RAW_LT_RE = /<(?![A-Za-z_:\/?!])/
|
|
99
|
+
RAW_LT_TRIGGER_RE = /<[^A-Za-z_:\/?!]/
|
|
96
100
|
|
|
97
101
|
def normalize_serialization(xml, options)
|
|
98
102
|
# The libxml2-layout serializer (>= 1.9.42) keeps attribute
|
|
99
103
|
# apostrophes literal; older engines escaped them.
|
|
100
104
|
needs_apos = !LIBXML2_LAYOUT_PARITY && xml.include?("'")
|
|
101
105
|
needs_expand = options[:expand_empty] && xml.include?("/>")
|
|
102
|
-
#
|
|
103
|
-
|
|
104
|
-
|
|
106
|
+
# Corruption guards: the 1-char ampersand probe is ~1µs
|
|
107
|
+
# (memchr-class); both regexes only run when their cheap
|
|
108
|
+
# necessary condition holds.
|
|
109
|
+
needs_amp = xml.include?("&") && xml.match?(RAW_AMP_RE)
|
|
110
|
+
needs_lt = xml.match?(RAW_LT_TRIGGER_RE)
|
|
105
111
|
return xml unless needs_apos || needs_expand || needs_amp || needs_lt
|
|
106
112
|
|
|
107
113
|
out = +""
|
|
@@ -288,6 +288,19 @@ module Moxml
|
|
|
288
288
|
return set_attribute_namespace(node, namespace) if node.is_a?(::Leptris::XML::Attr)
|
|
289
289
|
|
|
290
290
|
element = node
|
|
291
|
+
if namespace.nil?
|
|
292
|
+
# Nil-clear contract (issue #164): undeclare the default
|
|
293
|
+
# namespace (xmlns="") and drop any name prefix — the
|
|
294
|
+
# element then reports no namespace, matching the other
|
|
295
|
+
# adapters. Elements that carried a PREFIX cannot fully
|
|
296
|
+
# detach the engine's namespace link (leptris-ruby#132):
|
|
297
|
+
# the name is unqualified and the undeclaration added, but
|
|
298
|
+
# the serializer may re-attach the old prefix until the
|
|
299
|
+
# engine grows a clear entry.
|
|
300
|
+
element.name = element.name.split(":", 2)[-1] if element.name.include?(":")
|
|
301
|
+
element.default_namespace = ""
|
|
302
|
+
return element
|
|
303
|
+
end
|
|
291
304
|
prefix = namespace.is_a?(String) ? nil : namespace.prefix
|
|
292
305
|
uri = namespace.is_a?(String) ? namespace : namespace.href
|
|
293
306
|
if prefix.nil? || prefix.empty?
|
data/lib/moxml/adapter/oga.rb
CHANGED
|
@@ -170,6 +170,12 @@ module Moxml
|
|
|
170
170
|
end
|
|
171
171
|
|
|
172
172
|
def set_namespace(element, ns_or_string)
|
|
173
|
+
if ns_or_string.nil?
|
|
174
|
+
element.namespace_name = nil
|
|
175
|
+
set_attribute(element, "xmlns", "")
|
|
176
|
+
return element
|
|
177
|
+
end
|
|
178
|
+
|
|
173
179
|
element.namespace_name = ns_or_string.to_s
|
|
174
180
|
element
|
|
175
181
|
end
|
data/lib/moxml/adapter/ox.rb
CHANGED
|
@@ -149,6 +149,12 @@ module Moxml
|
|
|
149
149
|
def set_namespace(element, ns)
|
|
150
150
|
return element unless element.is_a?(::Ox::Element) || element.is_a?(::Ox::Node)
|
|
151
151
|
|
|
152
|
+
if ns.nil?
|
|
153
|
+
set_attribute(element, "xmlns", "")
|
|
154
|
+
element.name = element.name.to_s.sub(/\A(?:\w+):/, "")
|
|
155
|
+
return element
|
|
156
|
+
end
|
|
157
|
+
|
|
152
158
|
prefix = ns.prefix
|
|
153
159
|
# attributes don't have attributes but can have a namespace prefix
|
|
154
160
|
if element.is_a?(::Ox::Element)
|
data/lib/moxml/adapter/rexml.rb
CHANGED
|
@@ -485,6 +485,14 @@ module Moxml
|
|
|
485
485
|
|
|
486
486
|
# add a namespace prefix to the element name AND a namespace definition
|
|
487
487
|
def set_namespace(element, ns)
|
|
488
|
+
if ns.nil?
|
|
489
|
+
# Nil-clear contract (issue #164): the XML Namespaces 1.0
|
|
490
|
+
# undeclaration, plus an unqualified name.
|
|
491
|
+
element.add_namespace(nil, "") if element.is_a?(::REXML::Element)
|
|
492
|
+
element.name = element.name.to_s.sub(/\A(?:\w+):/, "")
|
|
493
|
+
return element
|
|
494
|
+
end
|
|
495
|
+
|
|
488
496
|
prefix = ns.name.to_s.empty? ? "xmlns" : ns.name.to_s
|
|
489
497
|
if element.is_a?(::REXML::Element)
|
|
490
498
|
element.add_namespace(prefix,
|
data/lib/moxml/version.rb
CHANGED
|
@@ -280,6 +280,12 @@ RSpec.shared_examples "Moxml::Namespace" do
|
|
|
280
280
|
expect(root.namespace.uri).to eq("http://example.org/1")
|
|
281
281
|
expect(child.namespace.uri).to eq("http://example.org/2")
|
|
282
282
|
end
|
|
283
|
+
|
|
284
|
+
it "accepts namespace = nil without raising (issue #164)" do
|
|
285
|
+
cleared = context.parse(%(<r xmlns="urn:clear"><c>t</c></r>))
|
|
286
|
+
child = cleared.root.children.first
|
|
287
|
+
expect { child.namespace = nil }.not_to raise_error
|
|
288
|
+
end
|
|
283
289
|
end
|
|
284
290
|
end
|
|
285
291
|
end
|
|
@@ -273,6 +273,25 @@ RSpec.describe Moxml::Adapter::Leptris do
|
|
|
273
273
|
end
|
|
274
274
|
end
|
|
275
275
|
|
|
276
|
+
it "clears the namespace with nil — full contract (issue #164)" do
|
|
277
|
+
doc = ctx.parse(%(<r xmlns="urn:clear"><c>t</c></r>))
|
|
278
|
+
child = doc.root.children.first
|
|
279
|
+
child.namespace = nil
|
|
280
|
+
expect(child.namespace).to be_nil
|
|
281
|
+
expect(doc.to_xml).to include(%(<c xmlns="">t</c>))
|
|
282
|
+
reparsed = ctx.parse(doc.to_xml)
|
|
283
|
+
expect(reparsed.root.children.first.namespace).to be_nil
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
it "does not raise clearing a namespace from a prefixed element (issue #164)" do
|
|
287
|
+
# The engine cannot detach a prefix element's namespace link
|
|
288
|
+
# (leptris-ruby#132); the name is unqualified and the
|
|
289
|
+
# undeclaration added meanwhile.
|
|
290
|
+
doc = ctx.parse(%(<r xmlns:p="urn:p"><p:c>t</p:c></r>))
|
|
291
|
+
child = doc.root.children.first
|
|
292
|
+
expect { child.namespace = nil }.not_to raise_error
|
|
293
|
+
end
|
|
294
|
+
|
|
276
295
|
it "refuses noblanks on readonly parses while the strip path is active" do
|
|
277
296
|
# The strip mutates the tree; readonly freezes it at parse. On
|
|
278
297
|
# bindings whose engine flag is libxml2-safe (probe), the flag
|
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.5.
|
|
4
|
+
version: 0.5.29
|
|
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-09-
|
|
11
|
+
date: 2026-09-04 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
|