@@ -156,19 +156,38 @@ impl super::Element for (&uppsala::Document<'_>, uppsala::NodeId) {
156156 // NOTE: I assume that ids are stable when cloning
157157 let el = doc. element_mut ( self . 1 ) . unwrap ( ) ;
158158
159+ // Collect inherited namespace declarations from ancestors of the current
160+ // element. We must be careful to not shadow these with a prefix that
161+ // only differs by case.
162+ let mut inherited_ns: std:: collections:: HashMap < & str , & str > =
163+ std:: collections:: HashMap :: new ( ) ;
164+ for ancestor_id in self . 0 . ancestors ( self . 1 ) . into_iter ( ) . rev ( ) {
165+ if let Some ( ancestor_el) = self . 0 . element ( ancestor_id) {
166+ for ( prefix, uri) in & ancestor_el. namespace_declarations {
167+ inherited_ns. insert ( prefix. as_ref ( ) , uri. as_ref ( ) ) ;
168+ }
169+ }
170+ }
171+
159172 // copy in all the active mappings as xmlns
160173 // this is simpler than tracking whether we need to add them as xmlns
161174 // or as prefixes, and it matches what the test suite does
162175 let mut prefixes = Vec :: new ( ) ;
163176 for ( prefix, value) in active_mappings. mappings ( ) {
164177 // note that there's a little tricky case where a prefix redefined a xmlns
165178 // in which case we need to ensure that _both_ are present on child nodes
166- // so the XML side and the RDFa side remain correct
167- if el
179+ // so the XML side and the RDFa side remain correct.
180+ // We must also check inherited ancestor namespaces — a lowercased @prefix
181+ // colliding with an inherited xmlns would corrupt element name resolution.
182+ let conflicts_with_existing = el
168183 . namespace_declarations
169184 . iter ( )
170185 . any ( |( p, v) | p == prefix && v != value)
171- {
186+ || inherited_ns
187+ . get ( prefix. as_str ( ) )
188+ . is_some_and ( |v| * v != value) ;
189+
190+ if conflicts_with_existing {
172191 prefixes. push ( ( prefix, value) ) ;
173192 } else {
174193 el. namespace_declarations
@@ -197,7 +216,7 @@ impl super::Element for (&uppsala::Document<'_>, uppsala::NodeId) {
197216 if !prefix_attr. is_empty ( ) {
198217 prefix_attr. push ( ' ' ) ;
199218 }
200- _ = write ! ( prefix_attr, "{prefix}: {value} " ) ;
219+ _ = write ! ( prefix_attr, "{prefix}: {value}" ) ;
201220 }
202221 }
203222 if !prefix_attr. is_empty ( ) {
0 commit comments