pub struct NamespaceResolver { /* private fields */ }
Expand description
A storage for currently defined namespace bindings, which is used to resolve prefixes into namespaces.
Holds all internal logic to push/pop namespaces with their levels.
Implementations§
Source§impl NamespaceResolver
impl NamespaceResolver
Sourcepub fn add(
&mut self,
prefix: PrefixDeclaration<'_>,
namespace: Namespace<'_>,
) -> Result<(), NamespaceError>
pub fn add( &mut self, prefix: PrefixDeclaration<'_>, namespace: Namespace<'_>, ) -> Result<(), NamespaceError>
Adds new binding of prefix to namespace, returns the result of operation.
Binding will be added on current nesting level and will be removed, when level will be popped out.
The operation may fail if you try to (re-)declare reserved prefixes xml
and xmlns
.
Note, that method does not check if namespace was already added on that level.
Use resolver.bindings_of(resolver.level()).any()
if you want to check that.
New definition will be added and replace the old.
Implementation detail: memory occupied by old binding of that level still will be used.
let mut resolver = NamespaceResolver::default();
// names without prefix are unbound by default
assert_eq!(
resolver.resolve_element(QName(b"name")).0,
ResolveResult::Unbound,
);
// names with undeclared prefix are unknown
assert_eq!(
resolver.resolve_element(QName(b"ns:name")).0,
ResolveResult::Unknown(b"ns".to_vec()),
);
resolver.add(PrefixDeclaration::Default, Namespace(b"example.com"));
resolver.add(PrefixDeclaration::Named(b"ns"), Namespace(b"my:namespace"));
assert_eq!(
resolver.resolve_element(QName(b"name")).0,
ResolveResult::Bound(Namespace(b"example.com")),
);
assert_eq!(
resolver.resolve_element(QName(b"ns:name")).0,
ResolveResult::Bound(Namespace(b"my:namespace")),
);
// adding empty namespace clears the binding
resolver.add(PrefixDeclaration::Default, Namespace(b""));
resolver.add(PrefixDeclaration::Named(b"ns"), Namespace(b""));
assert_eq!(
resolver.resolve_element(QName(b"name")).0,
ResolveResult::Unbound,
);
assert_eq!(
resolver.resolve_element(QName(b"ns:name")).0,
ResolveResult::Unknown(b"ns".to_vec()),
);
Sourcepub fn push(&mut self, start: &BytesStart<'_>) -> Result<(), NamespaceError>
pub fn push(&mut self, start: &BytesStart<'_>) -> Result<(), NamespaceError>
Begins a new scope and add to it all namespace bindings that found in the specified start element.
Sourcepub fn pop(&mut self)
pub fn pop(&mut self)
Ends a top-most scope by popping all namespace bindings, that was added by
last call to Self::push()
and Self::add()
.
Sourcepub fn resolve<'n>(
&self,
name: QName<'n>,
use_default: bool,
) -> (ResolveResult<'_>, LocalName<'n>)
pub fn resolve<'n>( &self, name: QName<'n>, use_default: bool, ) -> (ResolveResult<'_>, LocalName<'n>)
Resolves a potentially qualified element name or attribute name into (namespace name, local name).
Qualified names have the form local-name
or prefix:local-name
where the prefix
is defined on any containing XML element via xmlns:prefix="the:namespace:uri"
.
The namespace prefix can be defined on the same element as the name in question.
The method returns following results depending on the name
shape, attribute
flag
and the presence of the default namespace on element or any of its parents:
use_default | xmlns="..." | QName | ResolveResult | LocalName |
---|---|---|---|---|
false | (any) | local-name | Unbound | local-name |
false | (any) | prefix:local-name | Bound / Unknown | local-name |
true | Not defined | local-name | Unbound | local-name |
true | Defined | local-name | Bound (to xmlns ) | local-name |
true | (any) | prefix:local-name | Bound / Unknown | local-name |
§Parameters
name
: probably qualified name to resolve;use_default
: whether to try to translateNone
prefix to the currently default namespace (bound usingxmlns="default namespace"
) or returnResolveResult::Unbound
. For attribute names this should be set tofalse
and for element names totrue
.
§Lifetimes
'n
: lifetime of a name. Returned local name will be bound to the same lifetime as the name in question.- returned namespace name will be bound to the resolver itself
Sourcepub fn resolve_element<'n>(
&self,
name: QName<'n>,
) -> (ResolveResult<'_>, LocalName<'n>)
pub fn resolve_element<'n>( &self, name: QName<'n>, ) -> (ResolveResult<'_>, LocalName<'n>)
Convenient method to call resolve(name, true)
. May be used to clearly
express that we want to resolve an element name, and not an attribute name.
Sourcepub fn resolve_attribute<'n>(
&self,
name: QName<'n>,
) -> (ResolveResult<'_>, LocalName<'n>)
pub fn resolve_attribute<'n>( &self, name: QName<'n>, ) -> (ResolveResult<'_>, LocalName<'n>)
Convenient method to call resolve(name, false)
. May be used to clearly
express that we want to resolve an attribute name, and not an element name.
Sourcepub fn resolve_event<'i>(
&self,
event: Event<'i>,
) -> (ResolveResult<'_>, Event<'i>)
pub fn resolve_event<'i>( &self, event: Event<'i>, ) -> (ResolveResult<'_>, Event<'i>)
Finds a namespace name for a given event, if applicable.
Namespace is resolved only for Start
, Empty
and End
events.
For all other events the concept of namespace is not defined, so
a ResolveResult::Unbound
is returned.
§Examples
use quick_xml::events::Event;
use quick_xml::name::{Namespace, QName, ResolveResult::*};
use quick_xml::reader::NsReader;
let mut reader = NsReader::from_str(r#"
<x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
<y:tag2><!--Test comment-->Test</y:tag2>
<y:tag2>Test 2</y:tag2>
</x:tag1>
"#);
reader.config_mut().trim_text(true);
let mut count = 0;
let mut txt = Vec::new();
loop {
let event = reader.read_event().unwrap();
match reader.resolver().resolve_event(event) {
(Bound(Namespace(b"www.xxxx")), Event::Start(e)) => {
count += 1;
assert_eq!(e.local_name(), QName(b"tag1").into());
}
(Bound(Namespace(b"www.yyyy")), Event::Start(e)) => {
count += 1;
assert_eq!(e.local_name(), QName(b"tag2").into());
}
(_, Event::Start(_)) => unreachable!(),
(_, Event::Text(e)) => {
txt.push(e.decode().unwrap().into_owned())
}
(_, Event::Eof) => break,
_ => (),
}
}
assert_eq!(count, 3);
assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);
Sourcepub fn resolve_prefix(
&self,
prefix: Option<Prefix<'_>>,
use_default: bool,
) -> ResolveResult<'_>
pub fn resolve_prefix( &self, prefix: Option<Prefix<'_>>, use_default: bool, ) -> ResolveResult<'_>
Resolves given optional prefix (usually got from QName
) into a corresponding namespace.
§Parameters
prefix
: prefix to resolve, usually result ofQName::prefix()
;use_default
: whether to try to translateNone
prefix to the currently default namespace (bound usingxmlns="default namespace"
) or returnResolveResult::Unbound
. For attribute names this should be set tofalse
and for element names totrue
.
Sourcepub const fn bindings(&self) -> NamespaceBindingsIter<'_> ⓘ
pub const fn bindings(&self) -> NamespaceBindingsIter<'_> ⓘ
Returns all the bindings currently in effect except the default xml
and xmlns
bindings.
§Examples
This example shows what results the returned iterator would return after reading each event of a simple XML.
use quick_xml::name::{Namespace, PrefixDeclaration};
use quick_xml::NsReader;
let src = "<root>
<a xmlns=\"a1\" xmlns:a=\"a2\">
<b xmlns=\"b1\" xmlns:b=\"b2\">
<c/>
</b>
<d/>
</a>
</root>";
let mut reader = NsReader::from_str(src);
reader.config_mut().trim_text(true);
// No bindings at the beginning
assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![]);
reader.read_resolved_event()?; // <root>
// No bindings declared on root
assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![]);
reader.read_resolved_event()?; // <a>
// Two bindings declared on "a"
assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![
(PrefixDeclaration::Default, Namespace(b"a1")),
(PrefixDeclaration::Named(b"a"), Namespace(b"a2"))
]);
reader.read_resolved_event()?; // <b>
// The default prefix got overridden and new "b" prefix
assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![
(PrefixDeclaration::Named(b"a"), Namespace(b"a2")),
(PrefixDeclaration::Default, Namespace(b"b1")),
(PrefixDeclaration::Named(b"b"), Namespace(b"b2"))
]);
reader.read_resolved_event()?; // <c/>
// Still the same
assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![
(PrefixDeclaration::Named(b"a"), Namespace(b"a2")),
(PrefixDeclaration::Default, Namespace(b"b1")),
(PrefixDeclaration::Named(b"b"), Namespace(b"b2"))
]);
reader.read_resolved_event()?; // </b>
// Still the same
assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![
(PrefixDeclaration::Named(b"a"), Namespace(b"a2")),
(PrefixDeclaration::Default, Namespace(b"b1")),
(PrefixDeclaration::Named(b"b"), Namespace(b"b2"))
]);
reader.read_resolved_event()?; // <d/>
// </b> got closed so back to the bindings declared on <a>
assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![
(PrefixDeclaration::Default, Namespace(b"a1")),
(PrefixDeclaration::Named(b"a"), Namespace(b"a2"))
]);
reader.read_resolved_event()?; // </a>
// Still the same
assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![
(PrefixDeclaration::Default, Namespace(b"a1")),
(PrefixDeclaration::Named(b"a"), Namespace(b"a2"))
]);
reader.read_resolved_event()?; // </root>
// <a> got closed
assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![]);
Sourcepub const fn bindings_of(&self, level: u16) -> NamespaceBindingsOfLevelIter<'_> ⓘ
pub const fn bindings_of(&self, level: u16) -> NamespaceBindingsOfLevelIter<'_> ⓘ
Returns all the bindings on the specified level, including the default
xml
and xmlns
bindings.
§Parameters
level
: the nesting level of an XML tag. The document without tags has level 0, at which default bindings are declared. The root tag has level 1 and all other tags has levels > 1. If specify level more than current, the empty iterator is returned.
§Examples
This example shows what results the returned iterator would return on each level after reaning some events of a simple XML.
use quick_xml::name::{Namespace, PrefixDeclaration};
use quick_xml::NsReader;
let src = "<root>
<a xmlns=\"a1\" xmlns:a=\"a2\">
<b xmlns=\"b1\" xmlns:b=\"b2\">
<c/>
</b>
<d/>
</a>
</root>";
let mut reader = NsReader::from_str(src);
reader.config_mut().trim_text(true);
reader.read_resolved_event()?; // <root>
reader.read_resolved_event()?; // <a>
reader.read_resolved_event()?; // <b>
reader.read_resolved_event()?; // <c/>
// Default bindings at the beginning
assert_eq!(reader.resolver().bindings_of(0).collect::<Vec<_>>(), vec![
(PrefixDeclaration::Named(b"xml"), Namespace(b"http://www.w3.org/XML/1998/namespace")),
(PrefixDeclaration::Named(b"xmlns"), Namespace(b"http://www.w3.org/2000/xmlns/")),
]);
// No bindings declared on root
assert_eq!(reader.resolver().bindings_of(1).collect::<Vec<_>>(), vec![]);
// Two bindings declared on "a"
assert_eq!(reader.resolver().bindings_of(2).collect::<Vec<_>>(), vec![
(PrefixDeclaration::Default, Namespace(b"a1")),
(PrefixDeclaration::Named(b"a"), Namespace(b"a2")),
]);
// Two bindings declared on "b"
assert_eq!(reader.resolver().bindings_of(3).collect::<Vec<_>>(), vec![
(PrefixDeclaration::Default, Namespace(b"b1")),
(PrefixDeclaration::Named(b"b"), Namespace(b"b2")),
]);
// No bindings declared on "c"
assert_eq!(reader.resolver().bindings_of(4).collect::<Vec<_>>(), vec![]);
// No bindings on non-existent level
assert_eq!(reader.resolver().bindings_of(5).collect::<Vec<_>>(), vec![]);
Sourcepub const fn level(&self) -> u16
pub const fn level(&self) -> u16
Returns the number of push
calls that were not followed by pop
calls.
Due to use of u16
for level number the number of nested tags in XML
are limited by u16::MAX
, but that is enough for any real application.
§Example
let mut resolver = NamespaceResolver::default();
assert_eq!(resolver.level(), 0);
resolver.push(&BytesStart::new("tag"));
assert_eq!(resolver.level(), 1);
resolver.pop();
assert_eq!(resolver.level(), 0);
// pop from empty resolver does nothing
resolver.pop();
assert_eq!(resolver.level(), 0);
Trait Implementations§
Source§impl Clone for NamespaceResolver
impl Clone for NamespaceResolver
Source§fn clone(&self) -> NamespaceResolver
fn clone(&self) -> NamespaceResolver
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read more