@@ -71,6 +71,41 @@ impl<'a> QName<'a> {
7171 }
7272 }
7373
74+ /// If that `QName` represents `"xmlns"` series of names, returns `Some`,
75+ /// otherwise `None` is returned.
76+ ///
77+ /// # Examples
78+ ///
79+ /// ```
80+ /// # use quick_xml::name::{QName, PrefixDeclaration};
81+ /// let qname = QName(b"xmlns");
82+ /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Default));
83+ ///
84+ /// let qname = QName(b"xmlns:prefix");
85+ /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Named(b"prefix")));
86+ ///
87+ /// // Be aware that this method does not check the validity of the prefix - it can be empty!
88+ /// let qname = QName(b"xmlns:");
89+ /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Named(b"")));
90+ ///
91+ /// let qname = QName(b"other-name");
92+ /// assert_eq!(qname.as_namespace_binding(), None);
93+ ///
94+ /// // https://www.w3.org/TR/xml-names11/#xmlReserved
95+ /// let qname = QName(b"xmlns-reserved-name");
96+ /// assert_eq!(qname.as_namespace_binding(), None);
97+ /// ```
98+ pub fn as_namespace_binding ( & self ) -> Option < PrefixDeclaration < ' a > > {
99+ if self . 0 . starts_with ( b"xmlns" ) {
100+ return match self . 0 . get ( 5 ) {
101+ None => Some ( PrefixDeclaration :: Default ) ,
102+ Some ( & b':' ) => Some ( PrefixDeclaration :: Named ( & self . 0 [ 6 ..] ) ) ,
103+ _ => None ,
104+ } ;
105+ }
106+ None
107+ }
108+
74109 /// Returns the index in the name where prefix ended
75110 #[ inline( always) ]
76111 fn index ( & self ) -> Option < usize > {
@@ -173,6 +208,19 @@ impl<'a> AsRef<[u8]> for Prefix<'a> {
173208
174209////////////////////////////////////////////////////////////////////////////////////////////////////
175210
211+ /// A namespace prefix declaration, `xmlns` or `xmlns:<name>`, as defined in
212+ /// [XML Schema specification](https://www.w3.org/TR/xml-names/#ns-decl)
213+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
214+ pub enum PrefixDeclaration < ' a > {
215+ /// XML attribute binds a default namespace. Corresponds to `xmlns` in in `xmlns="..."`
216+ Default ,
217+ /// XML attribute binds a specified prefix to a namespace. Corresponds to a
218+ /// `prefix` in `xmlns:prefix="..."`, which is stored as payload of this variant.
219+ Named ( & ' a [ u8 ] ) ,
220+ }
221+
222+ ////////////////////////////////////////////////////////////////////////////////////////////////////
223+
176224/// A [namespace name] that is declared in a `xmlns[:prefix]="namespace name"`.
177225///
178226/// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName
@@ -361,32 +409,29 @@ impl NamespaceResolver {
361409 // (default namespace) attribute.
362410 for a in start. attributes ( ) . with_checks ( false ) {
363411 if let Ok ( Attribute { key : k, value : v } ) = a {
364- let k = k. as_ref ( ) ; //TODO: Use QName API
365- if k. starts_with ( b"xmlns" ) {
366- match k. get ( 5 ) {
367- None => {
368- let start = buffer. len ( ) ;
369- buffer. extend_from_slice ( & * v) ;
370- self . bindings . push ( NamespaceEntry {
371- start,
372- prefix_len : 0 ,
373- value_len : v. len ( ) ,
374- level,
375- } ) ;
376- }
377- Some ( & b':' ) => {
378- let start = buffer. len ( ) ;
379- buffer. extend_from_slice ( & k[ 6 ..] ) ;
380- buffer. extend_from_slice ( & * v) ;
381- self . bindings . push ( NamespaceEntry {
382- start,
383- prefix_len : k. len ( ) - 6 ,
384- value_len : v. len ( ) ,
385- level,
386- } ) ;
387- }
388- _ => break ,
412+ match k. as_namespace_binding ( ) {
413+ Some ( PrefixDeclaration :: Default ) => {
414+ let start = buffer. len ( ) ;
415+ buffer. extend_from_slice ( & * v) ;
416+ self . bindings . push ( NamespaceEntry {
417+ start,
418+ prefix_len : 0 ,
419+ value_len : v. len ( ) ,
420+ level,
421+ } ) ;
422+ }
423+ Some ( PrefixDeclaration :: Named ( prefix) ) => {
424+ let start = buffer. len ( ) ;
425+ buffer. extend_from_slice ( prefix) ;
426+ buffer. extend_from_slice ( & * v) ;
427+ self . bindings . push ( NamespaceEntry {
428+ start,
429+ prefix_len : prefix. len ( ) ,
430+ value_len : v. len ( ) ,
431+ level,
432+ } ) ;
389433 }
434+ None => { }
390435 }
391436 } else {
392437 break ;
0 commit comments