diff --git a/src/name.rs b/src/name.rs index 7ac207c1..0baf1e53 100644 --- a/src/name.rs +++ b/src/name.rs @@ -617,6 +617,28 @@ impl NamespaceResolver { None => ResolveResult::Unbound, } } + + #[inline] + pub fn iter(&self) -> impl Iterator { + self.bindings[2..].iter().enumerate().filter_map(|(i, n)| { + // We check if the key has not been overriden + if self.bindings[i + 3..] + .iter() + .any(|n2| n.prefix(&self.buffer) == n2.prefix(&self.buffer)) + { + return None; // Overriden + } + let prefix = if let Some(Prefix(prefix)) = n.prefix(&self.buffer) { + PrefixDeclaration::Named(prefix) + } else { + PrefixDeclaration::Default + }; + let ResolveResult::Bound(namespace) = n.namespace(&self.buffer) else { + return None; // We don't return unbound namespaces + }; + Some((prefix, namespace)) + }) + } } #[cfg(test)] diff --git a/src/reader/ns_reader.rs b/src/reader/ns_reader.rs index d5b79e78..3b70545a 100644 --- a/src/reader/ns_reader.rs +++ b/src/reader/ns_reader.rs @@ -12,7 +12,9 @@ use std::path::Path; use crate::errors::Result; use crate::events::Event; -use crate::name::{LocalName, NamespaceResolver, QName, ResolveResult}; +use crate::name::{ + LocalName, Namespace, NamespaceResolver, PrefixDeclaration, QName, ResolveResult, +}; use crate::reader::{Config, Reader, Span, XmlSource}; /// A low level encoding-agnostic XML event reader that performs namespace resolution. @@ -48,6 +50,12 @@ impl NsReader { pub fn config_mut(&mut self) -> &mut Config { self.reader.config_mut() } + + /// Returns all the prefixes currently declared except the default xml: and xmlns: namespaces. + #[inline] + pub fn prefixes(&self) -> impl Iterator { + self.ns_resolver.iter() + } } /// Private methods diff --git a/tests/namespaces.rs b/tests/namespaces.rs index 749aed7a..b1ac578f 100644 --- a/tests/namespaces.rs +++ b/tests/namespaces.rs @@ -2,7 +2,7 @@ use pretty_assertions::assert_eq; use quick_xml::events::attributes::Attribute; use quick_xml::events::Event::*; use quick_xml::name::ResolveResult::*; -use quick_xml::name::{Namespace, QName}; +use quick_xml::name::{Namespace, PrefixDeclaration, QName}; use quick_xml::reader::NsReader; use std::borrow::Cow; @@ -28,6 +28,11 @@ fn namespace() { e ), } + assert_eq!( + r.prefixes().collect::>(), + vec![(PrefixDeclaration::Named(b"myns"), Namespace(b"www1"))] + ); + // "in namespace!" match r.read_resolved_event() { Ok((ns, Text(_))) => assert_eq!(ns, Unbound), @@ -71,6 +76,11 @@ fn default_namespace() { e ), } + assert_eq!( + r.prefixes().collect::>(), + vec![(PrefixDeclaration::Default, Namespace(b"www1"))] + ); + // match r.read_resolved_event() { Ok((ns, End(_))) => assert_eq!(ns, Bound(Namespace(b"www1"))), @@ -110,6 +120,8 @@ fn default_namespace_reset() { e ), } + assert_eq!(r.prefixes().collect::>(), vec![]); + // match r.read_resolved_event() { Ok((ns, End(_))) => assert_eq!(ns, Unbound), @@ -257,6 +269,11 @@ fn default_ns_shadowing_empty() { Some((Unbound, &b"att1"[..], Cow::Borrowed(&b"a"[..]))) ); assert_eq!(attrs.next(), None); + + assert_eq!( + r.prefixes().collect::>(), + vec![(PrefixDeclaration::Default, Namespace(b"urn:example:i")),] + ); } //