canon 0.3.67 → 0.3.68
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/docs/features/match-options/index.adoc +33 -0
- data/docs/guides/choosing-configuration.adoc +23 -0
- data/lib/canon/comparison/dimensions/registry.rb +4 -0
- data/lib/canon/comparison/match_options/xml_resolver.rb +7 -1
- data/lib/canon/comparison/xml_comparator/namespace_comparator.rb +37 -0
- data/lib/canon/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 590320aa865898c6342d5c96566e6313e678a6d6f31a4d1e9463a50c9f434052
|
|
4
|
+
data.tar.gz: 6daacd998c4d52ae54096bc91329cd48686d33b7942970313891f8d69edf2141
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5d9fe69844ee374debb42557852bdcfd3d8cd3cadb30d15f01c2e2b932ad7412339107996bb2c88f04669951b88752856c56b812d2fd4ecbd3f993390b682efe
|
|
7
|
+
data.tar.gz: bfee82458261d1b20f78d7745da3cf620ce9beff2a993c01edcf6ff1d22f2538e8ddf7c45f21237e64f41a0218d0a25432dffcf0ea6cbcff3443cd416d4a677b
|
|
@@ -486,6 +486,33 @@ Canon::Comparison.equivalent?(html1, html2,
|
|
|
486
486
|
|
|
487
487
|
`:strict`:: Namespace URIs must match (default and only supported behavior)
|
|
488
488
|
|
|
489
|
+
=== namespace_prefix
|
|
490
|
+
|
|
491
|
+
**Applies to**: XML only
|
|
492
|
+
|
|
493
|
+
**Purpose**: Controls whether namespace *prefix spelling* is significant.
|
|
494
|
+
Per XML Namespaces, the prefix is a binding convenience — `xmlns:ns="http://x.example"`
|
|
495
|
+
and `xmlns:m="http://x.example"` bind to the same URI, so `<ns:e>` and `<m:e>` are the
|
|
496
|
+
same `{uri}local` name. Documents that round-trip through XML tooling (Office,
|
|
497
|
+
serializers) often churn prefixes; with `:ignore`, such documents compare
|
|
498
|
+
equivalent as long as the *set of declared URIs* matches. Namespace
|
|
499
|
+
declarations that resolve differently still report differences.
|
|
500
|
+
|
|
501
|
+
**Behaviors**:
|
|
502
|
+
|
|
503
|
+
`:significant`:: Prefix spelling matters — `xmlns:ns` and `xmlns:m` are
|
|
504
|
+
different declarations (default; `strict` and `rendered` profiles)
|
|
505
|
+
|
|
506
|
+
`:ignore`:: Only the set of declared namespace URIs matters
|
|
507
|
+
(`spec_friendly` and `content_only` profiles)
|
|
508
|
+
|
|
509
|
+
[source,ruby]
|
|
510
|
+
----
|
|
511
|
+
Canon::Comparison.equivalent?(xml1, xml2,
|
|
512
|
+
format: :xml,
|
|
513
|
+
match: { namespace_prefix: :ignore })
|
|
514
|
+
----
|
|
515
|
+
|
|
489
516
|
**Note**: This dimension is always `:strict` for XML. Namespace prefixes are not significant - only the namespace URI matters. Elements with different prefixes but the same namespace URI are considered equivalent.
|
|
490
517
|
|
|
491
518
|
.Namespace URI comparison
|
|
@@ -601,6 +628,12 @@ Each format has sensible defaults based on typical usage:
|
|
|
601
628
|
|—
|
|
602
629
|
|`:strict`
|
|
603
630
|
|
|
631
|
+
|`namespace_prefix`
|
|
632
|
+
|`:significant`
|
|
633
|
+
|`:significant`
|
|
634
|
+
|—
|
|
635
|
+
|—
|
|
636
|
+
|
|
604
637
|
|`namespace_uri`
|
|
605
638
|
|`:strict`
|
|
606
639
|
|—
|
|
@@ -9,6 +9,29 @@ nav_order: 1
|
|
|
9
9
|
|
|
10
10
|
Canon's 4-layer architecture provides powerful flexibility, but this can be overwhelming. This guide helps you choose the right configuration for your use case through decision trees, use case scenarios, and practical recommendations.
|
|
11
11
|
|
|
12
|
+
== XML namespace prefixes
|
|
13
|
+
|
|
14
|
+
If your documents round-trip through XML tooling (Office files, serializers,
|
|
15
|
+
XSLT processors), namespace *prefixes* often churn while the resolved names
|
|
16
|
+
stay identical (`xmlns:ns="http://x.example"` vs `xmlns:m="http://x.example"`). Canon's
|
|
17
|
+
default treats prefix spelling as significant; choose `:ignore` when the
|
|
18
|
+
binding, not the spelling, is what matters:
|
|
19
|
+
|
|
20
|
+
[source,ruby]
|
|
21
|
+
----
|
|
22
|
+
# Per comparison
|
|
23
|
+
Canon::Comparison.equivalent?(a, b,
|
|
24
|
+
format: :xml, match: { namespace_prefix: :ignore })
|
|
25
|
+
|
|
26
|
+
# Or per suite via config
|
|
27
|
+
Canon::Config.instance.xml.match.options[:namespace_prefix] = :ignore
|
|
28
|
+
----
|
|
29
|
+
|
|
30
|
+
The `spec_friendly` and `content_only` profiles already set
|
|
31
|
+
`namespace_prefix: :ignore`. Canonicalization output (`Canon.format`,
|
|
32
|
+
C14N) never rewrites prefixes regardless of this option — canonical bytes
|
|
33
|
+
stay spec-conformant.
|
|
34
|
+
|
|
12
35
|
== Quick Decision Tree
|
|
13
36
|
|
|
14
37
|
[mermaid]
|
|
@@ -23,6 +23,7 @@ module Canon
|
|
|
23
23
|
element_position: :ignore,
|
|
24
24
|
comments: :ignore,
|
|
25
25
|
whitespace_type: :strict,
|
|
26
|
+
namespace_prefix: :significant,
|
|
26
27
|
},
|
|
27
28
|
xml: {
|
|
28
29
|
preprocessing: :none,
|
|
@@ -34,6 +35,7 @@ module Canon
|
|
|
34
35
|
element_position: :strict,
|
|
35
36
|
comments: :strict,
|
|
36
37
|
whitespace_type: :strict,
|
|
38
|
+
namespace_prefix: :significant,
|
|
37
39
|
},
|
|
38
40
|
}.freeze
|
|
39
41
|
|
|
@@ -49,6 +51,7 @@ module Canon
|
|
|
49
51
|
element_position: :strict,
|
|
50
52
|
comments: :strict,
|
|
51
53
|
whitespace_type: :strict,
|
|
54
|
+
namespace_prefix: :significant,
|
|
52
55
|
},
|
|
53
56
|
|
|
54
57
|
rendered: {
|
|
@@ -56,11 +59,12 @@ module Canon
|
|
|
56
59
|
text_content: :normalize,
|
|
57
60
|
structural_whitespace: :normalize,
|
|
58
61
|
attribute_presence: :strict,
|
|
59
|
-
attribute_order: :
|
|
62
|
+
attribute_order: :ignore,
|
|
60
63
|
attribute_values: :strict,
|
|
61
64
|
element_position: :strict,
|
|
62
65
|
comments: :ignore,
|
|
63
66
|
whitespace_type: :strict,
|
|
67
|
+
namespace_prefix: :significant,
|
|
64
68
|
},
|
|
65
69
|
|
|
66
70
|
html4: {
|
|
@@ -97,6 +101,7 @@ module Canon
|
|
|
97
101
|
element_position: :ignore,
|
|
98
102
|
comments: :ignore,
|
|
99
103
|
whitespace_type: :strict,
|
|
104
|
+
namespace_prefix: :ignore,
|
|
100
105
|
},
|
|
101
106
|
|
|
102
107
|
content_only: {
|
|
@@ -109,6 +114,7 @@ module Canon
|
|
|
109
114
|
element_position: :ignore,
|
|
110
115
|
comments: :ignore,
|
|
111
116
|
whitespace_type: :strict,
|
|
117
|
+
namespace_prefix: :ignore,
|
|
112
118
|
},
|
|
113
119
|
}.freeze
|
|
114
120
|
|
|
@@ -20,6 +20,22 @@ module Canon
|
|
|
20
20
|
# Most element pairs declare nothing — skip the set algebra.
|
|
21
21
|
return Comparison::EQUIVALENT if ns_decls1.empty? && ns_decls2.empty?
|
|
22
22
|
|
|
23
|
+
# namespace_prefix: :ignore — prefix spelling is cosmetic;
|
|
24
|
+
# what resolves differently is the set of declared URIs
|
|
25
|
+
# (XML Namespaces: the prefix is a binding convenience, the
|
|
26
|
+
# {uri}local name is the name).
|
|
27
|
+
if opts[:match_opts][:namespace_prefix] == :ignore
|
|
28
|
+
uris1 = ns_decls1.values.uniq.sort
|
|
29
|
+
uris2 = ns_decls2.values.uniq.sort
|
|
30
|
+
return Comparison::EQUIVALENT if uris1 == uris2
|
|
31
|
+
|
|
32
|
+
missing = (ns_decls1.values.uniq - ns_decls2.values).sort
|
|
33
|
+
extra = (ns_decls2.values.uniq - ns_decls1.values).sort
|
|
34
|
+
add_namespace_uri_difference(node1, node2, missing, extra,
|
|
35
|
+
opts, differences)
|
|
36
|
+
return Comparison::UNEQUAL_ATTRIBUTES
|
|
37
|
+
end
|
|
38
|
+
|
|
23
39
|
# Find missing, extra, and changed namespace declarations
|
|
24
40
|
missing = ns_decls1.keys - ns_decls2.keys # In node1 but not node2
|
|
25
41
|
extra = ns_decls2.keys - ns_decls1.keys # In node2 but not node1
|
|
@@ -125,6 +141,27 @@ module Canon
|
|
|
125
141
|
Canon::Xml::NamespaceHelper.namespace_declaration?(attr_name)
|
|
126
142
|
end
|
|
127
143
|
|
|
144
|
+
# URI-flavored difference for namespace_prefix: :ignore —
|
|
145
|
+
# reports the URIs that resolve differently, not the prefix
|
|
146
|
+
# spellings.
|
|
147
|
+
def self.add_namespace_uri_difference(node1, node2, missing, extra,
|
|
148
|
+
opts, differences)
|
|
149
|
+
reasons = []
|
|
150
|
+
reasons << "removed URIs: #{missing.join(', ')}" if missing.any?
|
|
151
|
+
reasons << "added URIs: #{extra.join(', ')}" if extra.any?
|
|
152
|
+
|
|
153
|
+
diff_node = Canon::Comparison::DiffNodeBuilder.build(
|
|
154
|
+
node1: node1,
|
|
155
|
+
node2: node2,
|
|
156
|
+
diff1: Comparison::UNEQUAL_ATTRIBUTES,
|
|
157
|
+
diff2: Comparison::UNEQUAL_ATTRIBUTES,
|
|
158
|
+
dimension: :namespace_declarations,
|
|
159
|
+
**opts,
|
|
160
|
+
)
|
|
161
|
+
diff_node.reason = reasons.join("; ") if diff_node && reasons.any?
|
|
162
|
+
differences << diff_node if diff_node
|
|
163
|
+
end
|
|
164
|
+
|
|
128
165
|
# Add a namespace declaration difference
|
|
129
166
|
#
|
|
130
167
|
# @param node1 [Object] First node
|
data/lib/canon/version.rb
CHANGED