Skip to content

Commit 58bb2b6

Browse files
committed
Add ability to get current nesting level from the resolver and list of defined bindings on each level
1 parent 9f1a557 commit 58bb2b6

File tree

1 file changed

+152
-3
lines changed

1 file changed

+152
-3
lines changed

src/name.rs

Lines changed: 152 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ struct NamespaceBinding {
448448
/// Level of nesting at which this namespace was declared. The declaring element is included,
449449
/// i.e., a declaration on the document root has `level = 1`.
450450
/// This is used to pop the namespace when the element gets closed.
451-
level: i32,
451+
level: u16,
452452
}
453453

454454
impl NamespaceBinding {
@@ -491,7 +491,7 @@ pub struct NamespaceResolver {
491491
bindings: Vec<NamespaceBinding>,
492492
/// The number of open tags at the moment. We need to keep track of this to know which namespace
493493
/// declarations to remove when we encounter an `End` event.
494-
nesting_level: i32,
494+
nesting_level: u16,
495495
}
496496

497497
/// That constant define the one of [reserved namespaces] for the xml standard.
@@ -613,7 +613,7 @@ impl NamespaceResolver {
613613
///
614614
/// [namespace bindings]: https://www.w3.org/TR/xml-names11/#dt-NSDecl
615615
pub fn pop(&mut self) {
616-
self.nesting_level -= 1;
616+
self.nesting_level = self.nesting_level.saturating_sub(1);
617617
let current_level = self.nesting_level;
618618
// from the back (most deeply nested scope), look for the first scope that is still valid
619619
match self.bindings.iter().rposition(|n| n.level <= current_level) {
@@ -866,6 +866,111 @@ impl NamespaceResolver {
866866
cursor: 2,
867867
}
868868
}
869+
870+
/// Returns all the bindings on the specified level, including the default
871+
/// `xml` and `xmlns` bindings.
872+
///
873+
/// # Parameters
874+
/// - `level`: the nesting level of an XML tag. The document without tags has
875+
/// level 0, at which default bindings are declared. The root tag has level 1
876+
/// and all other tags has levels > 1. If specify level more than [current], the
877+
/// empty iterator is returned.
878+
///
879+
/// # Examples
880+
///
881+
/// This example shows what results the returned iterator would return on each
882+
/// level after reaning some events of a simple XML.
883+
///
884+
/// ```
885+
/// # use pretty_assertions::assert_eq;
886+
/// use quick_xml::name::{Namespace, PrefixDeclaration};
887+
/// use quick_xml::NsReader;
888+
///
889+
/// let src = "<root>
890+
/// <a xmlns=\"a1\" xmlns:a=\"a2\">
891+
/// <b xmlns=\"b1\" xmlns:b=\"b2\">
892+
/// <c/>
893+
/// </b>
894+
/// <d/>
895+
/// </a>
896+
/// </root>";
897+
/// let mut reader = NsReader::from_str(src);
898+
/// reader.config_mut().trim_text(true);
899+
/// reader.read_resolved_event()?; // <root>
900+
/// reader.read_resolved_event()?; // <a>
901+
/// reader.read_resolved_event()?; // <b>
902+
/// reader.read_resolved_event()?; // <c/>
903+
///
904+
/// // Default bindings at the beginning
905+
/// assert_eq!(reader.resolver().bindings_of(0).collect::<Vec<_>>(), vec![
906+
/// (PrefixDeclaration::Named(b"xml"), Namespace(b"http://www.w3.org/XML/1998/namespace")),
907+
/// (PrefixDeclaration::Named(b"xmlns"), Namespace(b"http://www.w3.org/2000/xmlns/")),
908+
/// ]);
909+
///
910+
/// // No bindings declared on root
911+
/// assert_eq!(reader.resolver().bindings_of(1).collect::<Vec<_>>(), vec![]);
912+
///
913+
/// // Two bindings declared on "a"
914+
/// assert_eq!(reader.resolver().bindings_of(2).collect::<Vec<_>>(), vec![
915+
/// (PrefixDeclaration::Default, Namespace(b"a1")),
916+
/// (PrefixDeclaration::Named(b"a"), Namespace(b"a2")),
917+
/// ]);
918+
///
919+
/// // Two bindings declared on "b"
920+
/// assert_eq!(reader.resolver().bindings_of(3).collect::<Vec<_>>(), vec![
921+
/// (PrefixDeclaration::Default, Namespace(b"b1")),
922+
/// (PrefixDeclaration::Named(b"b"), Namespace(b"b2")),
923+
/// ]);
924+
///
925+
/// // No bindings declared on "c"
926+
/// assert_eq!(reader.resolver().bindings_of(4).collect::<Vec<_>>(), vec![]);
927+
///
928+
/// // No bindings on non-existent level
929+
/// assert_eq!(reader.resolver().bindings_of(5).collect::<Vec<_>>(), vec![]);
930+
/// # quick_xml::Result::Ok(())
931+
/// ```
932+
///
933+
/// [current]: Self::level
934+
pub const fn bindings_of(&self, level: u16) -> NamespaceBindingsOfLevelIter<'_> {
935+
NamespaceBindingsOfLevelIter {
936+
resolver: self,
937+
cursor: 0,
938+
level,
939+
}
940+
}
941+
942+
/// Returns the number of [`push`] calls that were not followed by [`pop`] calls.
943+
///
944+
/// Due to use of `u16` for level number the number of nested tags in XML
945+
/// are limited by [`u16::MAX`], but that is enough for any real application.
946+
///
947+
/// # Example
948+
///
949+
/// ```
950+
/// # use pretty_assertions::assert_eq;
951+
/// # use quick_xml::events::BytesStart;
952+
/// # use quick_xml::name::{Namespace, NamespaceResolver, PrefixDeclaration, QName, ResolveResult};
953+
/// #
954+
/// let mut resolver = NamespaceResolver::default();
955+
///
956+
/// assert_eq!(resolver.level(), 0);
957+
///
958+
/// resolver.push(&BytesStart::new("tag"));
959+
/// assert_eq!(resolver.level(), 1);
960+
///
961+
/// resolver.pop();
962+
/// assert_eq!(resolver.level(), 0);
963+
///
964+
/// // pop from empty resolver does nothing
965+
/// resolver.pop();
966+
/// assert_eq!(resolver.level(), 0);
967+
/// ```
968+
///
969+
/// [`push`]: Self::push
970+
/// [`pop`]: Self::pop
971+
pub const fn level(&self) -> u16 {
972+
self.nesting_level
973+
}
869974
}
870975

871976
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -918,6 +1023,50 @@ impl<'a> FusedIterator for NamespaceBindingsIter<'a> {}
9181023
#[deprecated = "Use NamespaceBindingsIter instead"]
9191024
pub type PrefixIter<'a> = NamespaceBindingsIter<'a>;
9201025

1026+
/// Iterator on the declared namespace bindings on specified level. Returns pairs of the _(prefix, namespace)_.
1027+
///
1028+
/// See [`NamespaceResolver::bindings_of`] for documentation.
1029+
#[derive(Debug, Clone)]
1030+
pub struct NamespaceBindingsOfLevelIter<'a> {
1031+
resolver: &'a NamespaceResolver,
1032+
cursor: usize,
1033+
level: u16,
1034+
}
1035+
1036+
impl<'a> Iterator for NamespaceBindingsOfLevelIter<'a> {
1037+
type Item = (PrefixDeclaration<'a>, Namespace<'a>);
1038+
1039+
fn next(&mut self) -> Option<(PrefixDeclaration<'a>, Namespace<'a>)> {
1040+
while let Some(binding) = self.resolver.bindings.get(self.cursor) {
1041+
self.cursor += 1; // We increment for next read
1042+
if binding.level < self.level {
1043+
continue;
1044+
}
1045+
if binding.level > self.level {
1046+
break;
1047+
}
1048+
1049+
if let ResolveResult::Bound(namespace) = binding.namespace(&self.resolver.buffer) {
1050+
let prefix = match binding.prefix(&self.resolver.buffer) {
1051+
Some(Prefix(prefix)) => PrefixDeclaration::Named(prefix),
1052+
None => PrefixDeclaration::Default,
1053+
};
1054+
return Some((prefix, namespace));
1055+
}
1056+
}
1057+
None // We have exhausted the array
1058+
}
1059+
1060+
fn size_hint(&self) -> (usize, Option<usize>) {
1061+
// Real count could be less
1062+
(0, Some(self.resolver.bindings.len() - self.cursor))
1063+
}
1064+
}
1065+
1066+
impl<'a> FusedIterator for NamespaceBindingsOfLevelIter<'a> {}
1067+
1068+
////////////////////////////////////////////////////////////////////////////////////////////////////
1069+
9211070
#[cfg(test)]
9221071
mod namespaces {
9231072
use super::*;

0 commit comments

Comments
 (0)