@@ -8,6 +8,8 @@ use crate::events::attributes::Attribute;
8
8
use crate :: events:: BytesStart ;
9
9
use crate :: utils:: write_byte_string;
10
10
use memchr:: memchr;
11
+ use once_cell:: sync:: Lazy ;
12
+ use std:: collections:: HashMap ;
11
13
use std:: convert:: TryFrom ;
12
14
use std:: fmt:: { self , Debug , Formatter } ;
13
15
@@ -399,6 +401,32 @@ pub(crate) struct NamespaceResolver {
399
401
nesting_level : i32 ,
400
402
}
401
403
404
+ /// These constants define the reserved namespaces for the xml standard.
405
+ ///
406
+ /// The prefix `xml` is by definition bound to the namespace name
407
+ /// `http://www.w3.org/XML/1998/namespace`. It may, but need not, be declared, and must not be
408
+ /// undeclared or bound to any other namespace name. Other prefixes must not be bound to this
409
+ /// namespace name, and it must not be declared as the default namespace.
410
+ ///
411
+ /// The prefix `xmlns` is used only to declare namespace bindings and is by definition bound
412
+ /// to the namespace name http://www.w3.org/2000/xmlns/. It must not be declared or
413
+ /// undeclared. Other prefixes must not be bound to this namespace name, and it must not be
414
+ /// declared as the default namespace. Element names must not have the prefix xmlns.
415
+ ///
416
+ /// [reserved namespaces]: https://www.w3.org/TR/xml-names11/#xmlReserved
417
+ static WELL_KNOWN_NAMESPACES : Lazy < HashMap < Prefix , Namespace > > = Lazy :: new ( || {
418
+ let mut m = HashMap :: new ( ) ;
419
+ m. insert (
420
+ Prefix ( b"xml" ) ,
421
+ Namespace ( b"http://www.w3.org/XML/1998/namespace" ) ,
422
+ ) ;
423
+ m. insert (
424
+ Prefix ( b"xmlns" ) ,
425
+ Namespace ( b"http://www.w3.org/2000/xmlns/" ) ,
426
+ ) ;
427
+ m
428
+ } ) ;
429
+
402
430
impl NamespaceResolver {
403
431
/// Begins a new scope and add to it all [namespace bindings] that found in
404
432
/// the specified start element.
@@ -542,7 +570,10 @@ impl NamespaceResolver {
542
570
#[ inline]
543
571
fn maybe_unknown ( prefix : Option < Prefix > ) -> ResolveResult < ' static > {
544
572
match prefix {
545
- Some ( p) => ResolveResult :: Unknown ( p. into_inner ( ) . to_vec ( ) ) ,
573
+ Some ( p) => WELL_KNOWN_NAMESPACES . get ( & p) . map_or_else (
574
+ || ResolveResult :: Unknown ( p. into_inner ( ) . to_vec ( ) ) ,
575
+ |p| ResolveResult :: Bound ( * p) ,
576
+ ) ,
546
577
None => ResolveResult :: Unbound ,
547
578
}
548
579
}
@@ -787,6 +818,32 @@ mod namespaces {
787
818
}
788
819
}
789
820
821
+ mod builtin_prefixes {
822
+ use super :: * ;
823
+ use pretty_assertions:: assert_eq;
824
+
825
+ #[ test]
826
+ fn undeclared_reserved_prefixes ( ) {
827
+ let resolver = NamespaceResolver :: default ( ) ;
828
+ let tag = b"random" ;
829
+
830
+ for ( prefix, namespace) in WELL_KNOWN_NAMESPACES . iter ( ) {
831
+ let name_buf = [ prefix. into_inner ( ) , tag] . join ( & b":" [ ..] ) ;
832
+ let name = QName ( & name_buf) ;
833
+
834
+ assert_eq ! (
835
+ resolver. resolve( name, b"" , true ) ,
836
+ ( Bound ( * namespace) , LocalName ( tag) )
837
+ ) ;
838
+ assert_eq ! (
839
+ resolver. resolve( name. clone( ) , b"" , false ) ,
840
+ ( Bound ( * namespace) , LocalName ( tag) )
841
+ ) ;
842
+ assert_eq ! ( resolver. find( name. clone( ) , b"" ) , Bound ( * namespace) ) ;
843
+ }
844
+ }
845
+ }
846
+
790
847
#[ test]
791
848
fn undeclared_prefix ( ) {
792
849
let name = QName ( b"unknown:prefix" ) ;
0 commit comments