@@ -545,60 +545,125 @@ impl Default for NamespaceResolver {
545545}
546546
547547impl NamespaceResolver {
548+ /// Adds new binding of prefix to namespace, returns the result of operation.
549+ ///
550+ /// Binding will be added on current nesting level and will be removed, when
551+ /// level will be [popped out].
552+ ///
553+ /// The operation may fail if you try to (re-)declare reserved prefixes `xml` and `xmlns`.
554+ ///
555+ /// Note, that method does not check if namespace was already added on that level.
556+ /// Use `resolver.bindings_of(resolver.level()).any()` if you want to check that.
557+ /// New definition will be added and replace the old.
558+ ///
559+ /// Implementation detail: memory occupied by old binding of that level still will be used.
560+ ///
561+ /// ```
562+ /// # use pretty_assertions::assert_eq;
563+ /// # use quick_xml::name::{Namespace, NamespaceResolver, PrefixDeclaration, QName, ResolveResult};
564+ /// #
565+ /// let mut resolver = NamespaceResolver::default();
566+ /// // names without prefix are unbound by default
567+ /// assert_eq!(
568+ /// resolver.resolve_element(QName(b"name")).0,
569+ /// ResolveResult::Unbound,
570+ /// );
571+ /// // names with undeclared prefix are unknown
572+ /// assert_eq!(
573+ /// resolver.resolve_element(QName(b"ns:name")).0,
574+ /// ResolveResult::Unknown(b"ns".to_vec()),
575+ /// );
576+ ///
577+ /// resolver.add(PrefixDeclaration::Default, Namespace(b"example.com"));
578+ /// resolver.add(PrefixDeclaration::Named(b"ns"), Namespace(b"my:namespace"));
579+ ///
580+ /// assert_eq!(
581+ /// resolver.resolve_element(QName(b"name")).0,
582+ /// ResolveResult::Bound(Namespace(b"example.com")),
583+ /// );
584+ /// assert_eq!(
585+ /// resolver.resolve_element(QName(b"ns:name")).0,
586+ /// ResolveResult::Bound(Namespace(b"my:namespace")),
587+ /// );
588+ ///
589+ /// // adding empty namespace clears the binding
590+ /// resolver.add(PrefixDeclaration::Default, Namespace(b""));
591+ /// resolver.add(PrefixDeclaration::Named(b"ns"), Namespace(b""));
592+ ///
593+ /// assert_eq!(
594+ /// resolver.resolve_element(QName(b"name")).0,
595+ /// ResolveResult::Unbound,
596+ /// );
597+ /// assert_eq!(
598+ /// resolver.resolve_element(QName(b"ns:name")).0,
599+ /// ResolveResult::Unknown(b"ns".to_vec()),
600+ /// );
601+ /// ```
602+ /// [popped out]: Self::pop
603+ pub fn add (
604+ & mut self ,
605+ prefix : PrefixDeclaration ,
606+ namespace : Namespace ,
607+ ) -> Result < ( ) , NamespaceError > {
608+ let level = self . nesting_level ;
609+ match prefix {
610+ PrefixDeclaration :: Default => {
611+ let start = self . buffer . len ( ) ;
612+ self . buffer . extend_from_slice ( & namespace. 0 ) ;
613+ self . bindings . push ( NamespaceBinding {
614+ start,
615+ prefix_len : 0 ,
616+ value_len : namespace. 0 . len ( ) ,
617+ level,
618+ } ) ;
619+ }
620+ PrefixDeclaration :: Named ( b"xml" ) => {
621+ if namespace != RESERVED_NAMESPACE_XML . 1 {
622+ // error, `xml` prefix explicitly set to different value
623+ return Err ( NamespaceError :: InvalidXmlPrefixBind ( namespace. 0 . to_vec ( ) ) ) ;
624+ }
625+ // don't add another NamespaceEntry for the `xml` namespace prefix
626+ }
627+ PrefixDeclaration :: Named ( b"xmlns" ) => {
628+ // error, `xmlns` prefix explicitly set
629+ return Err ( NamespaceError :: InvalidXmlnsPrefixBind ( namespace. 0 . to_vec ( ) ) ) ;
630+ }
631+ PrefixDeclaration :: Named ( prefix) => {
632+ // error, non-`xml` prefix set to xml uri
633+ if namespace == RESERVED_NAMESPACE_XML . 1 {
634+ return Err ( NamespaceError :: InvalidPrefixForXml ( prefix. to_vec ( ) ) ) ;
635+ } else
636+ // error, non-`xmlns` prefix set to xmlns uri
637+ if namespace == RESERVED_NAMESPACE_XMLNS . 1 {
638+ return Err ( NamespaceError :: InvalidPrefixForXmlns ( prefix. to_vec ( ) ) ) ;
639+ }
640+
641+ let start = self . buffer . len ( ) ;
642+ self . buffer . extend_from_slice ( prefix) ;
643+ self . buffer . extend_from_slice ( & namespace. 0 ) ;
644+ self . bindings . push ( NamespaceBinding {
645+ start,
646+ prefix_len : prefix. len ( ) ,
647+ value_len : namespace. 0 . len ( ) ,
648+ level,
649+ } ) ;
650+ }
651+ }
652+ Ok ( ( ) )
653+ }
654+
548655 /// Begins a new scope and add to it all [namespace bindings] that found in
549656 /// the specified start element.
550657 ///
551658 /// [namespace bindings]: https://www.w3.org/TR/xml-names11/#dt-NSDecl
552659 pub fn push ( & mut self , start : & BytesStart ) -> Result < ( ) , NamespaceError > {
553660 self . nesting_level += 1 ;
554- let level = self . nesting_level ;
555661 // adds new namespaces for attributes starting with 'xmlns:' and for the 'xmlns'
556662 // (default namespace) attribute.
557663 for a in start. attributes ( ) . with_checks ( false ) {
558664 if let Ok ( Attribute { key : k, value : v } ) = a {
559665 match k. as_namespace_binding ( ) {
560- Some ( PrefixDeclaration :: Default ) => {
561- let start = self . buffer . len ( ) ;
562- self . buffer . extend_from_slice ( & v) ;
563- self . bindings . push ( NamespaceBinding {
564- start,
565- prefix_len : 0 ,
566- value_len : v. len ( ) ,
567- level,
568- } ) ;
569- }
570- Some ( PrefixDeclaration :: Named ( b"xml" ) ) => {
571- if Namespace ( & v) != RESERVED_NAMESPACE_XML . 1 {
572- // error, `xml` prefix explicitly set to different value
573- return Err ( NamespaceError :: InvalidXmlPrefixBind ( v. to_vec ( ) ) ) ;
574- }
575- // don't add another NamespaceEntry for the `xml` namespace prefix
576- }
577- Some ( PrefixDeclaration :: Named ( b"xmlns" ) ) => {
578- // error, `xmlns` prefix explicitly set
579- return Err ( NamespaceError :: InvalidXmlnsPrefixBind ( v. to_vec ( ) ) ) ;
580- }
581- Some ( PrefixDeclaration :: Named ( prefix) ) => {
582- let ns = Namespace ( & v) ;
583-
584- if ns == RESERVED_NAMESPACE_XML . 1 {
585- // error, non-`xml` prefix set to xml uri
586- return Err ( NamespaceError :: InvalidPrefixForXml ( prefix. to_vec ( ) ) ) ;
587- } else if ns == RESERVED_NAMESPACE_XMLNS . 1 {
588- // error, non-`xmlns` prefix set to xmlns uri
589- return Err ( NamespaceError :: InvalidPrefixForXmlns ( prefix. to_vec ( ) ) ) ;
590- }
591-
592- let start = self . buffer . len ( ) ;
593- self . buffer . extend_from_slice ( prefix) ;
594- self . buffer . extend_from_slice ( & v) ;
595- self . bindings . push ( NamespaceBinding {
596- start,
597- prefix_len : prefix. len ( ) ,
598- value_len : v. len ( ) ,
599- level,
600- } ) ;
601- }
666+ Some ( prefix) => self . add ( prefix, Namespace ( & v) ) ?,
602667 None => { }
603668 }
604669 } else {
@@ -609,7 +674,7 @@ impl NamespaceResolver {
609674 }
610675
611676 /// Ends a top-most scope by popping all [namespace bindings], that was added by
612- /// last call to [`Self::push()`].
677+ /// last call to [`Self::push()`] and [`Self::add()`] .
613678 ///
614679 /// [namespace bindings]: https://www.w3.org/TR/xml-names11/#dt-NSDecl
615680 pub fn pop ( & mut self ) {
0 commit comments