Skip to main content

NsReader

Struct NsReader 

Source
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>

Source

pub async fn read_event_into_async<'b>( &mut self, buf: &'b mut Vec<u8>, ) -> Result<Event<'b>>

Available on crate feature 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.

Source

pub 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.

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.

Source

pub 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.

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.

Source

pub 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.

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

Source

pub fn from_reader(reader: R) -> Self

Creates a NsReader that reads from a given reader.

Source

pub const fn config(&self) -> &Config

Returns reference to the parser configuration.

Source

pub fn config_mut(&mut self) -> &mut Config

Returns mutable reference to the parser configuration.

Source§

impl<R> NsReader<R>

Getters

Source

pub fn into_inner(self) -> R

Consumes NsReader returning the underlying reader.

See Reader::into_inner for examples.

Source

pub const fn get_ref(&self) -> &R

Gets a reference to the underlying reader.

Source

pub fn get_mut(&mut self) -> &mut R

Gets a mutable reference to the underlying reader.

Source

pub const fn resolver(&self) -> &NamespaceResolver

Returns the storage of namespace bindings associated with this reader.

Source

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.

Source

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 by xmlns="...") is applied;
  • if true (the attribute case), an unprefixed name is always Unbound, 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()),
);
Source

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()),
    );
}
Source

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).

Source

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>

Source

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()]);
Source

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);
Source

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().

Source

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 NsReader<BufReader<File>>

Source

pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self>

Creates an XML reader from a file path.

Source§

impl<'i> NsReader<&'i [u8]>

Source

pub fn from_str(s: &'i str) -> Self

Creates an XML reader from a string slice.

Source

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()]);
Source

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);
Source

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)
);
Source

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>>§

Source

pub fn config(&self) -> &Config

Returns reference to the parser configuration

Source

pub fn get_ref(&self) -> &R

Gets a reference to the underlying reader.

Source

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.

Source

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().

Source

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.

Trait Implementations§

Source§

impl<R: Clone> Clone for NsReader<R>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<R: Debug> Debug for NsReader<R>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<R> Deref for NsReader<R>

Source§

type Target = Reader<R>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.

Auto Trait Implementations§

§

impl<R> Freeze for NsReader<R>
where Reader<R>: Freeze,

§

impl<R> RefUnwindSafe for NsReader<R>

§

impl<R> Send for NsReader<R>
where Reader<R>: Send,

§

impl<R> Sync for NsReader<R>
where Reader<R>: Sync,

§

impl<R> Unpin for NsReader<R>
where Reader<R>: Unpin,

§

impl<R> UnsafeUnpin for NsReader<R>
where Reader<R>: UnsafeUnpin,

§

impl<R> UnwindSafe for NsReader<R>
where Reader<R>: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.