@@ -41,22 +41,32 @@ def self.merge_string(main_strings, library, string_line)
41
41
return :skipped if skip_string_by_exclusion_list ( library , string_name )
42
42
43
43
# Search for the string in the main file
44
+ result = :added
44
45
main_strings . xpath ( '//string' ) . each do | this_string |
45
46
if ( this_string . attr ( "name" ) == string_name ) then
46
47
# Skip if the string has the content_override tag
47
48
return :skipped if skip_string_by_tag ( this_string )
48
49
49
- # Update if needed
50
- ( if ( this_string . content == string_content ) then return :found else this_string . content = string_content ; return :updated end )
50
+ # If nodes are equivalent, skip
51
+ return :found if ( string_line =~ this_string )
52
+
53
+ # The string needs an update
54
+ result = :updated
55
+ if ( this_string . attr ( "tools:ignore" ) . nil? )
56
+ # It can be updated, so remove the current one and move ahead
57
+ this_string . remove
58
+ break
59
+ else
60
+ # It has the tools:ignore flag, so update the content without touching the other attributes
61
+ this_string . content = string_content
62
+ return result
63
+ end
51
64
end
52
65
end
53
66
54
- # String not found and not in the exclusion list: add to the main file
55
- new_element = Nokogiri ::XML ::Node . new "string" , main_strings
56
- new_element [ 'name' ] = string_name
57
- new_element . content = string_content
58
- main_strings . xpath ( '//string' ) . last ( ) . add_next_sibling ( "\n #{ " " * 4 } #{ new_element . to_xml ( ) } " )
59
- return :added
67
+ # String not found, or removed because needing update and not in the exclusion list: add to the main file
68
+ main_strings . xpath ( '//string' ) . last ( ) . add_next_sibling ( "\n #{ " " * 4 } #{ string_line . to_xml ( ) . strip } " )
69
+ return result
60
70
end
61
71
62
72
# Verify a string
@@ -169,3 +179,27 @@ def self.verify_pr_diff(main, library, main_strings, lib_strings, source_diff)
169
179
end
170
180
end
171
181
end
182
+
183
+ # Source: https://stackoverflow.com/questions/7825258/determine-if-two-nokogiri-nodes-are-equivalent?rq=1
184
+ # There may be better solutions now that Ruby supports canonicalization.
185
+ class Nokogiri ::XML ::Node
186
+ # Return true if this node is content-equivalent to other, false otherwise
187
+ def =~( other )
188
+ return true if self == other
189
+ return false unless name == other . name
190
+ stype = node_type ; otype = other . node_type
191
+ return false unless stype == otype
192
+ sa = attributes ; oa = other . attributes
193
+ return false unless sa . length == oa . length
194
+ sa = sa . sort . map { |n , a | [ n , a . value , a . namespace && a . namespace . href ] }
195
+ oa = oa . sort . map { |n , a | [ n , a . value , a . namespace && a . namespace . href ] }
196
+ return false unless sa == oa
197
+ skids = children ; okids = other . children
198
+ return false unless skids . length == okids . length
199
+ return false if stype == TEXT_NODE && ( content != other . content )
200
+ sns = namespace ; ons = other . namespace
201
+ return false if !sns ^ !ons
202
+ return false if sns && ( sns . href != ons . href )
203
+ skids . to_enum . with_index . all? { |ski , i | ski =~ okids [ i ] }
204
+ end
205
+ end
0 commit comments