pub struct NsReader<R> { /* private fields */ }Expand description
A low level encoding-agnostic XML event reader that performs namespace resolution.
Consumes bytes and streams XML Events, tracking the namespace declarations
(xmlns and xmlns:* attributes) as elements are opened and closed. Unlike the
plain Reader, names emitted by this reader can be resolved
to their namespace.
The reader dereferences to the underlying Reader, so all of its inspection
methods (buffer_position,
error_position, decoder, …)
are available directly.
§Examples
use oxixml_xml::events::Event;
use oxixml_xml::name::{Namespace, ResolveResult::*};
use oxixml_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 {
match reader.read_event().expect("valid event") {
Event::Start(e) => {
count += 1;
let (ns, local) = reader.resolve_element(e.name());
match local.as_ref() {
b"tag1" => assert_eq!(ns, Bound(Namespace(b"www.xxxx"))),
b"tag2" => assert_eq!(ns, Bound(Namespace(b"www.yyyy"))),
_ => unreachable!(),
}
}
Event::Text(e) => txt.push(e.decode().expect("utf-8").into_owned()),
Event::Eof => break,
_ => (),
}
}
assert_eq!(count, 3);
assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);Implementations§
Source§impl<R: AsyncBufRead + Unpin> NsReader<R>
impl<R: AsyncBufRead + Unpin> NsReader<R>
Sourcepub async fn read_event_into_async<'b>(
&mut self,
buf: &'b mut Vec<u8>,
) -> Result<Event<'b>>
Available on crate feature async-tokio only.
pub async fn read_event_into_async<'b>( &mut self, buf: &'b mut Vec<u8>, ) -> Result<Event<'b>>
async-tokio only.An asynchronous version of read_event_into(). Reads the next event
into the given buffer.
This method manages namespaces but doesn’t resolve them automatically.
You should call resolve_element() if you want to get a namespace.
You also can use read_resolved_event_into_async() instead if you want
to resolve namespaces as soon as you get an event.
Sourcepub async fn read_to_end_into_async<'n>(
&mut self,
end: QName<'n>,
buf: &mut Vec<u8>,
) -> Result<Span>
Available on crate feature async-tokio only.
pub async fn read_to_end_into_async<'n>( &mut self, end: QName<'n>, buf: &mut Vec<u8>, ) -> Result<Span>
async-tokio only.An asynchronous version of read_to_end_into(). Reads asynchronously
until the matching end element is found, using the provided buffer as
intermediate storage for events content. This function is supposed to be
called after you already read a Start event.
See the documentation of read_to_end_into() for more information.
Sourcepub async fn read_text_into_async<'n, 'b>(
&mut self,
end: QName<'n>,
buf: &'b mut Vec<u8>,
) -> Result<BytesText<'b>>
Available on crate feature async-tokio only.
pub async fn read_text_into_async<'n, 'b>( &mut self, end: QName<'n>, buf: &'b mut Vec<u8>, ) -> Result<BytesText<'b>>
async-tokio only.An asynchronous version of read_text_into(). Reads asynchronously
content between start and end tags, including any markup, using the
provided buffer as intermediate storage for events content. This
function is supposed to be called after you already read a Start
event.
See the documentation of read_text_into() for more information.
Sourcepub async fn read_resolved_event_into_async<'ns, 'b>(
&'ns mut self,
buf: &'b mut Vec<u8>,
) -> Result<(ResolveResult<'ns>, Event<'b>)>
Available on crate feature async-tokio only.
pub async fn read_resolved_event_into_async<'ns, 'b>( &'ns mut self, buf: &'b mut Vec<u8>, ) -> Result<(ResolveResult<'ns>, Event<'b>)>
async-tokio only.An asynchronous version of read_resolved_event_into(). Reads the next
event into the given buffer asynchronously and resolves its namespace
(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.
If you are not interested in namespaces, you can use
read_event_into_async() which will not automatically resolve
namespaces for you.
Source§impl<R> NsReader<R>
Builder methods
impl<R> NsReader<R>
Builder methods
Sourcepub fn from_reader(reader: R) -> Self
pub fn from_reader(reader: R) -> Self
Creates a NsReader that reads from a given reader.
Sourcepub fn config_mut(&mut self) -> &mut Config
pub fn config_mut(&mut self) -> &mut Config
Returns mutable reference to the parser configuration.
Source§impl<R> NsReader<R>
Getters
impl<R> NsReader<R>
Getters
Sourcepub fn into_inner(self) -> R
pub fn into_inner(self) -> R
Consumes NsReader returning the underlying reader.
See Reader::into_inner for examples.
Sourcepub const fn resolver(&self) -> &NamespaceResolver
pub const fn resolver(&self) -> &NamespaceResolver
Returns the storage of namespace bindings associated with this reader.
Sourcepub fn resolver_mut(&mut self) -> &mut NamespaceResolver
pub fn resolver_mut(&mut self) -> &mut NamespaceResolver
Returns a mutable reference to the storage of namespace bindings associated with this reader.
Useful for configuring the resolver, e.g. to change the per-element namespace-declaration limit.
Sourcepub fn resolve<'n>(
&self,
name: QName<'n>,
attribute: bool,
) -> (ResolveResult<'_>, LocalName<'n>)
pub fn resolve<'n>( &self, name: QName<'n>, attribute: bool, ) -> (ResolveResult<'_>, LocalName<'n>)
Resolves a potentially qualified name into (namespace name, local name).
Qualified names have the form prefix:local-name where the prefix is
defined by an xmlns:prefix="the:namespace:uri" binding on this element or
on any of its ancestors.
The attribute flag controls how a name without a prefix is resolved:
- if
false(the element case), the reader’s current default namespace (declared byxmlns="...") is applied; - if
true(the attribute case), an unprefixed name is alwaysUnbound, because a default namespace never applies to attribute names.
See also resolve_element and
resolve_attribute, which pick the flag for you.
§Example
use oxixml_xml::name::{Namespace, QName, ResolveResult::*};
use oxixml_xml::reader::NsReader;
let mut reader = NsReader::from_str("<tag one:x='1' two:y='2'/>");
let _ = reader.read_event().expect("empty");
// Note that this example is simplified — the bindings are not declared,
// so the prefixes are `Unknown` here.
assert_eq!(
reader.resolve(QName(b"one:x"), true),
(Unknown(b"one".to_vec()), QName(b"x").into()),
);Sourcepub fn resolve_element<'n>(
&self,
name: QName<'n>,
) -> (ResolveResult<'_>, LocalName<'n>)
pub fn resolve_element<'n>( &self, name: QName<'n>, ) -> (ResolveResult<'_>, LocalName<'n>)
Resolves a potentially qualified element name into (namespace name, local name).
An unprefixed element name resolves to the current default namespace, if any.
This is a convenience for resolve(name, false).
§Example
use oxixml_xml::events::Event;
use oxixml_xml::name::{Namespace, ResolveResult::*};
use oxixml_xml::reader::NsReader;
let mut reader = NsReader::from_str(r#"<tag xmlns="urn:d"/>"#);
if let Event::Empty(e) = reader.read_event().expect("empty") {
assert_eq!(
reader.resolve_element(e.name()),
(Bound(Namespace(b"urn:d")), e.local_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>)
Resolves a potentially qualified attribute name into (namespace name, local name).
An unprefixed attribute name is never bound to the default namespace, so it
resolves to Unbound. This is a convenience for
resolve(name, true).
Sourcepub fn prefixes(&self) -> NamespaceBindingsIter<'_> ⓘ
pub fn prefixes(&self) -> NamespaceBindingsIter<'_> ⓘ
Returns an iterator over the namespace bindings currently in scope, yielding
(prefix, namespace) pairs. The reserved xml and xmlns bindings are not
included.
§Example
use oxixml_xml::name::{Namespace, PrefixDeclaration};
use oxixml_xml::reader::NsReader;
let mut reader = NsReader::from_str(r#"<tag xmlns="d" xmlns:a="a1"/>"#);
let _ = reader.read_event().expect("empty");
assert_eq!(reader.prefixes().collect::<Vec<_>>(), vec![
(PrefixDeclaration::Default, Namespace(b"d")),
(PrefixDeclaration::Named(b"a"), Namespace(b"a1")),
]);Source§impl<R: BufRead> NsReader<R>
impl<R: BufRead> NsReader<R>
Sourcepub fn read_event_into<'b>(&mut self, buf: &'b mut Vec<u8>) -> Result<Event<'b>>
pub fn read_event_into<'b>(&mut self, buf: &'b mut Vec<u8>) -> Result<Event<'b>>
Reads the next event into the given buffer.
This method manages namespaces but doesn’t resolve them automatically. You
should call resolve_element if you want to get a
namespace.
You can also use read_resolved_event_into
instead if you want to resolve the namespace as soon as you get an event.
§Examples
use oxixml_xml::events::Event;
use oxixml_xml::name::{Namespace, ResolveResult::*};
use oxixml_xml::reader::NsReader;
let mut reader = NsReader::from_reader(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>
"#.as_bytes());
reader.config_mut().trim_text(true);
let mut count = 0;
let mut buf = Vec::new();
let mut txt = Vec::new();
loop {
match reader.read_event_into(&mut buf).expect("valid event") {
Event::Start(e) => {
count += 1;
let (ns, local) = reader.resolve_element(e.name());
match local.as_ref() {
b"tag1" => assert_eq!(ns, Bound(Namespace(b"www.xxxx"))),
b"tag2" => assert_eq!(ns, Bound(Namespace(b"www.yyyy"))),
_ => unreachable!(),
}
}
Event::Text(e) => txt.push(e.decode().expect("utf-8").into_owned()),
Event::Eof => break,
_ => (),
}
buf.clear();
}
assert_eq!(count, 3);
assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);Sourcepub fn read_resolved_event_into<'b>(
&mut self,
buf: &'b mut Vec<u8>,
) -> Result<(ResolveResult<'_>, Event<'b>)>
pub fn read_resolved_event_into<'b>( &mut self, buf: &'b mut Vec<u8>, ) -> Result<(ResolveResult<'_>, Event<'b>)>
Reads the next event into the given buffer and resolves its namespace (if applicable).
Namespace is resolved only for Start,
Empty and End events. For all other events
the concept of a namespace is not defined, so a
ResolveResult::Unbound is returned.
If you are not interested in namespaces, you can use
read_event_into which will not automatically
resolve namespaces for you.
§Examples
use oxixml_xml::events::Event;
use oxixml_xml::name::{Namespace, QName, ResolveResult::*};
use oxixml_xml::reader::NsReader;
let mut reader = NsReader::from_reader(r#"
<x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
<y:tag2><!--Test comment-->Test</y:tag2>
</x:tag1>
"#.as_bytes());
reader.config_mut().trim_text(true);
let mut count = 0;
let mut buf = Vec::new();
loop {
match reader.read_resolved_event_into(&mut buf).expect("valid 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::Eof) => break,
_ => (),
}
buf.clear();
}
assert_eq!(count, 2);Sourcepub fn read_to_end_into(
&mut self,
end: QName<'_>,
buf: &mut Vec<u8>,
) -> Result<Span>
pub fn read_to_end_into( &mut self, end: QName<'_>, buf: &mut Vec<u8>, ) -> Result<Span>
Reads until the matching end element is found, using the provided buffer as
intermediate storage for events content. This function is supposed to be
called after you already read a Start event.
Manages nested cases where parent and child elements have the literally same name.
If a corresponding End event is not found, an error of type
Error::IllFormed will be returned.
The end parameter should contain the name of the end element in the
reader encoding. It is good practice to always get that parameter using
BytesStart::to_end().
Sourcepub fn read_text_into<'b>(
&mut self,
end: QName<'_>,
buf: &'b mut Vec<u8>,
) -> Result<BytesText<'b>>
pub fn read_text_into<'b>( &mut self, end: QName<'_>, buf: &'b mut Vec<u8>, ) -> Result<BytesText<'b>>
Reads the content between start and end tags, including any markup, using the
provided buffer as intermediate storage for events content. This function is
supposed to be called after you already read a Start event.
Manages nested cases where parent and child elements have the literally same name.
This method does not unescape read data, instead it returns content “as is”.
Source§impl<'i> NsReader<&'i [u8]>
impl<'i> NsReader<&'i [u8]>
Sourcepub fn read_event(&mut self) -> Result<Event<'i>>
pub fn read_event(&mut self) -> Result<Event<'i>>
Reads the next event, borrowing its content from the input buffer.
This method manages namespaces but doesn’t resolve them automatically. You
should call resolve_element if you want to get a
namespace.
You can also use read_resolved_event instead
if you want to resolve the namespace as soon as you get an event.
§Examples
use oxixml_xml::events::Event;
use oxixml_xml::name::{Namespace, ResolveResult::*};
use oxixml_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 {
match reader.read_event().expect("valid event") {
Event::Start(e) => {
count += 1;
let (ns, local) = reader.resolve_element(e.name());
match local.as_ref() {
b"tag1" => assert_eq!(ns, Bound(Namespace(b"www.xxxx"))),
b"tag2" => assert_eq!(ns, Bound(Namespace(b"www.yyyy"))),
_ => unreachable!(),
}
}
Event::Text(e) => txt.push(e.decode().expect("utf-8").into_owned()),
Event::Eof => break,
_ => (),
}
}
assert_eq!(count, 3);
assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);Sourcepub fn read_resolved_event(&mut self) -> Result<(ResolveResult<'_>, Event<'i>)>
pub fn read_resolved_event(&mut self) -> Result<(ResolveResult<'_>, Event<'i>)>
Reads the next event, borrowing its content from the input buffer, and resolves its namespace (if applicable).
Namespace is resolved only for Start,
Empty and End events. For all other events
the concept of a namespace is not defined, so a
ResolveResult::Unbound is returned.
If you are not interested in namespaces, you can use
read_event which will not automatically resolve
namespaces for you.
§Examples
use oxixml_xml::events::Event;
use oxixml_xml::name::{Namespace, QName, ResolveResult::*};
use oxixml_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>
</x:tag1>
"#);
reader.config_mut().trim_text(true);
let mut count = 0;
loop {
match reader.read_resolved_event().expect("valid 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::Eof) => break,
_ => (),
}
}
assert_eq!(count, 2);Sourcepub fn read_to_end(&mut self, end: QName<'_>) -> Result<Span>
pub fn read_to_end(&mut self, end: QName<'_>) -> Result<Span>
Reads until the matching end element is found. This function is supposed to
be called after you already read a Start event.
Returns a span that covers the content between > of an opening tag and <
of a closing tag.
Manages nested cases where parent and child elements have the literally same name.
§Examples
use oxixml_xml::events::{BytesStart, Event};
use oxixml_xml::name::{Namespace, ResolveResult};
use oxixml_xml::reader::NsReader;
let mut reader = NsReader::from_str(r#"
<outer xmlns="namespace 1">
<inner xmlns="namespace 2">
<outer></outer>
</inner>
<inner>
<inner></inner>
<inner/>
<outer></outer>
<p:outer xmlns:p="ns"></p:outer>
<outer/>
</inner>
</outer>
"#);
reader.config_mut().trim_text(true);
let ns = Namespace(b"namespace 1");
let start = BytesStart::from_content(r#"outer xmlns="namespace 1""#, 5);
let end = start.to_end().into_owned();
assert_eq!(
reader.read_resolved_event().expect("start"),
(ResolveResult::Bound(ns), Event::Start(start))
);
// Skip all events to the corresponding end event, handling nested <outer>s.
reader.read_to_end(end.name()).expect("end");
assert_eq!(
reader.read_resolved_event().expect("eof"),
(ResolveResult::Unbound, Event::Eof)
);Sourcepub fn read_text(&mut self, end: QName<'_>) -> Result<BytesText<'i>>
pub fn read_text(&mut self, end: QName<'_>) -> Result<BytesText<'i>>
Reads content between start and end tags, including any markup. This function
is supposed to be called after you already read a Start
event.
Manages nested cases where parent and child elements have the literally same name.
This method does not unescape read data, instead it returns content “as is”.
Methods from Deref<Target = Reader<R>>§
Sourcepub fn buffer_position(&self) -> u64
pub fn buffer_position(&self) -> u64
Gets the byte position in the input data just after the last emitted event (i.e. this is position where data of last event ends).
Note, that for text events which is originally ended with whitespace characters
( , \t, \r, and \n) if Config::trim_text_end is set this is position
before trim, not the position of the last byte of the
Event::Text content.
Sourcepub fn error_position(&self) -> u64
pub fn error_position(&self) -> u64
Gets the last error byte position in the input data. If there is no errors
yet, returns 0.
Unlike buffer_position it will point to the place where it is rational
to report error to the end user. For example, all
SyntaxErrors are reported when the parser
sees EOF inside of some kind of markup. The buffer_position() will point
to the last byte of input which is not very useful. error_position() will
point to the start of corresponding markup element (i. e. to the < character).
This position is always <= buffer_position().
Sourcepub fn decoder(&self) -> Decoder
pub fn decoder(&self) -> Decoder
Get the decoder, used to decode bytes, read by this reader, to the strings.
If encoding feature is enabled, the used encoding may change after
parsing the XML declaration, otherwise encoding is fixed to UTF-8.
If encoding feature is enabled and no encoding is specified in declaration,
defaults to UTF-8.