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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 58c68ab8bd9ce6ae758ef8a9b2aeb69272dac07ef633e6d400dce01498e4a45a
4
- data.tar.gz: d118362c2a39b59d6739c67623b31d8a957c093e8b280360be969643041b15f2
3
+ metadata.gz: 590320aa865898c6342d5c96566e6313e678a6d6f31a4d1e9463a50c9f434052
4
+ data.tar.gz: 6daacd998c4d52ae54096bc91329cd48686d33b7942970313891f8d69edf2141
5
5
  SHA512:
6
- metadata.gz: dc4582dc42ff629f85115a37e5456f6339ec7fe27f6e9b568fa6af1096d42c362aa5eb6bd767ceb40fb8f2e0f781cf642cfecd454631e34e937961e5c5b3ca45
7
- data.tar.gz: d7c4b776c8720cd9c04bbc0b002d9a355ce23ea57668bb42df2bb7c3224a2a654776ff67ed8c0ad6b0c74a6173557ef650bb7a5f3f1178e042d379c8f833b6a6
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]
@@ -44,6 +44,10 @@ module Canon
44
44
  name: :comments,
45
45
  valid_behaviors: %i[strict ignore],
46
46
  ),
47
+ Dimension.new(
48
+ name: :namespace_prefix,
49
+ valid_behaviors: %i[significant ignore],
50
+ ),
47
51
  ]),
48
52
 
49
53
  json: DimensionSet.new(:json, [
@@ -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: :strict,
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Canon
4
- VERSION = "0.3.67"
4
+ VERSION = "0.3.68"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.67
4
+ version: 0.3.68
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.