Skip to content

Commit

Permalink
Adds NsReader::prefixes to iterate on all the prefixes currently decl…
Browse files Browse the repository at this point in the history
…ared

This is useful for some use cases like RDF/XML where prefixes might be interesting to extract
  • Loading branch information
Tpt committed Jan 14, 2024
1 parent de61fa1 commit 4a57bbf
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 2 deletions.
22 changes: 22 additions & 0 deletions src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,28 @@ impl NamespaceResolver {
None => ResolveResult::Unbound,
}
}

#[inline]
pub fn iter(&self) -> impl Iterator<Item = (PrefixDeclaration, Namespace)> {
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)]
Expand Down
10 changes: 9 additions & 1 deletion src/reader/ns_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -48,6 +50,12 @@ impl<R> NsReader<R> {
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<Item = (PrefixDeclaration, Namespace)> {
self.ns_resolver.iter()
}
}

/// Private methods
Expand Down
19 changes: 18 additions & 1 deletion tests/namespaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -28,6 +28,11 @@ fn namespace() {
e
),
}
assert_eq!(
r.prefixes().collect::<Vec<_>>(),
vec![(PrefixDeclaration::Named(b"myns"), Namespace(b"www1"))]
);

// "in namespace!"
match r.read_resolved_event() {
Ok((ns, Text(_))) => assert_eq!(ns, Unbound),
Expand Down Expand Up @@ -71,6 +76,11 @@ fn default_namespace() {
e
),
}
assert_eq!(
r.prefixes().collect::<Vec<_>>(),
vec![(PrefixDeclaration::Default, Namespace(b"www1"))]
);

// </b>
match r.read_resolved_event() {
Ok((ns, End(_))) => assert_eq!(ns, Bound(Namespace(b"www1"))),
Expand Down Expand Up @@ -110,6 +120,8 @@ fn default_namespace_reset() {
e
),
}
assert_eq!(r.prefixes().collect::<Vec<_>>(), vec![]);

// </b>
match r.read_resolved_event() {
Ok((ns, End(_))) => assert_eq!(ns, Unbound),
Expand Down Expand Up @@ -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<_>>(),
vec![(PrefixDeclaration::Default, Namespace(b"urn:example:i")),]
);
}

// </outer>
Expand Down

0 comments on commit 4a57bbf

Please sign in to comment.