Skip to main content

oxixml_xml/reader/
ns_reader.rs

1//! A reader that manages namespace declarations found in the input and is able
2//! to resolve [qualified names] to [expanded names].
3//!
4//! The central type is [`NsReader`], a thin namespace-aware wrapper over the
5//! low-level [`Reader`]. It mirrors the quick-xml 0.41 `NsReader`: it consumes
6//! bytes, streams XML [`Event`]s, and — for [`Start`](Event::Start),
7//! [`Empty`](Event::Empty) and [`End`](Event::End) events — tracks the in-scope
8//! `xmlns` bindings so that a [`QName`] can be resolved to its namespace.
9//!
10//! # Example
11//!
12//! ```
13//! use oxixml_xml::events::Event;
14//! use oxixml_xml::name::{Namespace, ResolveResult};
15//! use oxixml_xml::reader::NsReader;
16//!
17//! let mut reader = NsReader::from_str(r#"<tag xmlns="urn:example">text</tag>"#);
18//! match reader.read_resolved_event().expect("start") {
19//!     (ns, Event::Start(e)) => {
20//!         assert_eq!(ns, ResolveResult::Bound(Namespace(b"urn:example")));
21//!         assert_eq!(e.local_name().as_ref(), b"tag");
22//!     }
23//!     _ => panic!("expected a start event"),
24//! }
25//! ```
26//!
27//! [qualified names]: https://www.w3.org/TR/xml-names11/#dt-qualname
28//! [expanded names]: https://www.w3.org/TR/xml-names11/#dt-expname
29
30use std::fs::File;
31use std::io::{BufRead, BufReader};
32use std::ops::Deref;
33use std::path::Path;
34
35use crate::errors::{Result, WellFormedError};
36use crate::events::{BytesStart, BytesText, Event};
37use crate::name::{
38    LocalName, Namespace, NamespaceBindingsIter, NamespaceError, NamespaceResolver, QName,
39    ResolveResult,
40};
41use crate::reader::{Config, Reader, Span, XmlSource};
42
43/// A low level encoding-agnostic XML event reader that performs namespace resolution.
44///
45/// Consumes bytes and streams XML [`Event`]s, tracking the namespace declarations
46/// (`xmlns` and `xmlns:*` attributes) as elements are opened and closed. Unlike the
47/// plain [`Reader`], names emitted by this reader can be [resolved](Self::resolve)
48/// to their namespace.
49///
50/// The reader dereferences to the underlying [`Reader`], so all of its inspection
51/// methods ([`buffer_position`](Reader::buffer_position),
52/// [`error_position`](Reader::error_position), [`decoder`](Reader::decoder), …)
53/// are available directly.
54///
55/// # Examples
56///
57/// ```
58/// use oxixml_xml::events::Event;
59/// use oxixml_xml::name::{Namespace, ResolveResult::*};
60/// use oxixml_xml::reader::NsReader;
61///
62/// let mut reader = NsReader::from_str(r#"
63///     <x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
64///        <y:tag2><!--Test comment-->Test</y:tag2>
65///        <y:tag2>Test 2</y:tag2>
66///     </x:tag1>
67/// "#);
68/// reader.config_mut().trim_text(true);
69///
70/// let mut count = 0;
71/// let mut txt = Vec::new();
72/// loop {
73///     match reader.read_event().expect("valid event") {
74///         Event::Start(e) => {
75///             count += 1;
76///             let (ns, local) = reader.resolve_element(e.name());
77///             match local.as_ref() {
78///                 b"tag1" => assert_eq!(ns, Bound(Namespace(b"www.xxxx"))),
79///                 b"tag2" => assert_eq!(ns, Bound(Namespace(b"www.yyyy"))),
80///                 _ => unreachable!(),
81///             }
82///         }
83///         Event::Text(e) => txt.push(e.decode().expect("utf-8").into_owned()),
84///         Event::Eof => break,
85///         _ => (),
86///     }
87/// }
88/// assert_eq!(count, 3);
89/// assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);
90/// ```
91#[derive(Debug, Clone)]
92pub struct NsReader<R> {
93    /// An XML reader
94    pub(super) reader: Reader<R>,
95    /// A buffer to manage namespaces
96    ns_resolver: NamespaceResolver,
97    /// We cannot pop data from the namespace stack until the returned `Empty` or
98    /// `End` event has been processed by the user, so we only mark that we should
99    /// do that in the next [`Self::read_event_impl()`] call.
100    pending_pop: bool,
101}
102
103/// Builder methods
104impl<R> NsReader<R> {
105    /// Creates a `NsReader` that reads from a given reader.
106    #[inline]
107    pub fn from_reader(reader: R) -> Self {
108        Self::new(Reader::from_reader(reader))
109    }
110
111    /// Returns reference to the parser configuration.
112    #[inline]
113    pub const fn config(&self) -> &Config {
114        self.reader.config()
115    }
116
117    /// Returns mutable reference to the parser configuration.
118    #[inline]
119    pub fn config_mut(&mut self) -> &mut Config {
120        self.reader.config_mut()
121    }
122}
123
124/// Private methods
125impl<R> NsReader<R> {
126    #[inline]
127    fn new(mut reader: Reader<R>) -> Self {
128        reader.enable_namespace_constraints();
129        Self {
130            reader,
131            ns_resolver: NamespaceResolver::default(),
132            pending_pop: false,
133        }
134    }
135
136    fn read_event_impl<'i, B>(&mut self, buf: B) -> Result<Event<'i>>
137    where
138        R: XmlSource<'i, B>,
139    {
140        self.pop();
141        let event = self.reader.read_event_impl(buf);
142        self.process_event(event)
143    }
144
145    /// Pops the namespace scope of a previously-returned `Empty` or `End` event,
146    /// if one is pending.
147    ///
148    /// `pub(super)` so that the asynchronous implementation in the sibling
149    /// [`async_tokio`](super::async_tokio) module can reuse it.
150    pub(super) fn pop(&mut self) {
151        if self.pending_pop {
152            self.ns_resolver.pop();
153            self.pending_pop = false;
154        }
155    }
156
157    /// Updates the namespace resolver from a freshly read event, and schedules a
158    /// scope pop for `Empty` and `End` events.
159    ///
160    /// `pub(super)` so that the asynchronous implementation in the sibling
161    /// [`async_tokio`](super::async_tokio) module can reuse it.
162    pub(super) fn process_event<'i>(&mut self, event: Result<Event<'i>>) -> Result<Event<'i>> {
163        match event {
164            Ok(Event::Start(e)) => {
165                self.check_element_depth()?;
166                self.ns_resolver.push(&e)?;
167                self.check_namespace_constraints(&e)?;
168                Ok(Event::Start(e))
169            }
170            Ok(Event::Empty(e)) => {
171                self.check_element_depth()?;
172                self.ns_resolver.push(&e)?;
173                self.check_namespace_constraints(&e)?;
174                // Notify the next `read_event_impl()` call that it needs to pop
175                // this namespace scope.
176                self.pending_pop = true;
177                Ok(Event::Empty(e))
178            }
179            Ok(Event::End(e)) => {
180                // Notify the next `read_event_impl()` call that it needs to pop
181                // this namespace scope.
182                self.pending_pop = true;
183                Ok(Event::End(e))
184            }
185            e => e,
186        }
187    }
188
189    /// Rejects a `Start`/`Empty` event that would nest the namespace scope
190    /// deeper than [`Config::max_element_depth`], instead of letting the
191    /// scope stack grow without bound for a pathologically (or maliciously)
192    /// deep document.
193    ///
194    /// Called before [`NamespaceResolver::push`] so that a rejected event
195    /// never mutates the resolver: the scope simply never opens, rather than
196    /// having to be unwound after the fact.
197    fn check_element_depth(&self) -> Result<()> {
198        let max = self.reader.config().max_element_depth;
199        if self.ns_resolver.level() >= max {
200            return Err(NamespaceError::TooDeeplyNested(max).into());
201        }
202        Ok(())
203    }
204
205    /// Normalizes a namespace name so that two spellings differing only by
206    /// character references or by references to entities declared in the internal
207    /// subset compare equal, as section 2.3 of Namespaces in XML requires.
208    fn normalize_namespace(&self, uri: &[u8]) -> Vec<u8> {
209        let Ok(text) = std::str::from_utf8(uri) else {
210            return uri.to_vec();
211        };
212        match crate::escape::unescape_with(text, |name| self.reader.declared_entity(name)) {
213            Ok(unescaped) => unescaped.into_owned().into_bytes(),
214            Err(_) => uri.to_vec(),
215        }
216    }
217
218    /// Enforces the namespace constraints that need prefix resolution, namely
219    /// [Namespace Constraint: Prefix Declared] and the uniqueness of *expanded*
220    /// attribute names required by section 5.3 of Namespaces in XML.
221    ///
222    /// Only active when
223    /// [`Config::check_well_formedness`](crate::reader::Config::check_well_formedness)
224    /// is enabled; the default path stays `quick-xml`-compatible.
225    ///
226    /// [Namespace Constraint: Prefix Declared]: https://www.w3.org/TR/xml-names/#nsc-NSDeclared
227    fn check_namespace_constraints(&self, start: &BytesStart<'_>) -> Result<()> {
228        if !self.reader.config().check_well_formedness {
229            return Ok(());
230        }
231        if let ResolveResult::Unknown(prefix) = self.ns_resolver.resolve_element(start.name()).0 {
232            return Err(NamespaceError::UnknownPrefix(prefix).into());
233        }
234        let mut seen: Vec<(Option<Vec<u8>>, Vec<u8>)> = Vec::new();
235        for attribute in start.attributes() {
236            let attribute = attribute?;
237            let key = attribute.key;
238            if key.as_ref() == b"xmlns" || key.as_ref().starts_with(b"xmlns:") {
239                continue;
240            }
241            let (namespace, local) = self.ns_resolver.resolve_attribute(key);
242            let namespace = match namespace {
243                ResolveResult::Unknown(prefix) => {
244                    return Err(NamespaceError::UnknownPrefix(prefix).into());
245                }
246                ResolveResult::Bound(Namespace(uri)) => Some(self.normalize_namespace(uri)),
247                ResolveResult::Unbound => None,
248            };
249            let expanded = (namespace, local.as_ref().to_vec());
250            if seen.contains(&expanded) {
251                let name = String::from_utf8_lossy(key.as_ref()).into_owned();
252                return Err(WellFormedError::DuplicateAttribute(name).into());
253            }
254            seen.push(expanded);
255        }
256        Ok(())
257    }
258}
259
260/// Getters
261impl<R> NsReader<R> {
262    /// Consumes `NsReader` returning the underlying reader.
263    ///
264    /// See [`Reader::into_inner`] for examples.
265    #[inline]
266    pub fn into_inner(self) -> R {
267        self.reader.into_inner()
268    }
269
270    /// Gets a reference to the underlying reader.
271    #[inline]
272    pub const fn get_ref(&self) -> &R {
273        self.reader.get_ref()
274    }
275
276    /// Gets a mutable reference to the underlying reader.
277    #[inline]
278    pub fn get_mut(&mut self) -> &mut R {
279        self.reader.get_mut()
280    }
281
282    /// Returns the storage of namespace bindings associated with this reader.
283    #[inline]
284    pub const fn resolver(&self) -> &NamespaceResolver {
285        &self.ns_resolver
286    }
287
288    /// Returns a mutable reference to the storage of namespace bindings associated
289    /// with this reader.
290    ///
291    /// Useful for configuring the resolver, e.g. to change the
292    /// [per-element namespace-declaration limit](NamespaceResolver::set_max_declarations_per_element).
293    #[inline]
294    pub fn resolver_mut(&mut self) -> &mut NamespaceResolver {
295        &mut self.ns_resolver
296    }
297
298    /// Resolves a potentially qualified **name** into _(namespace name, local name)_.
299    ///
300    /// *Qualified* names have the form `prefix:local-name` where the `prefix` is
301    /// defined by an `xmlns:prefix="the:namespace:uri"` binding on this element or
302    /// on any of its ancestors.
303    ///
304    /// The `attribute` flag controls how a name **without** a prefix is resolved:
305    ///
306    /// - if `false` (the element case), the reader's current default namespace
307    ///   (declared by `xmlns="..."`) is applied;
308    /// - if `true` (the attribute case), an unprefixed name is always
309    ///   [`Unbound`](ResolveResult::Unbound), because a default namespace never
310    ///   applies to attribute names.
311    ///
312    /// See also [`resolve_element`](Self::resolve_element) and
313    /// [`resolve_attribute`](Self::resolve_attribute), which pick the flag for you.
314    ///
315    /// # Example
316    ///
317    /// ```
318    /// use oxixml_xml::name::{Namespace, QName, ResolveResult::*};
319    /// use oxixml_xml::reader::NsReader;
320    ///
321    /// let mut reader = NsReader::from_str("<tag one:x='1' two:y='2'/>");
322    /// let _ = reader.read_event().expect("empty");
323    ///
324    /// // Note that this example is simplified — the bindings are not declared,
325    /// // so the prefixes are `Unknown` here.
326    /// assert_eq!(
327    ///     reader.resolve(QName(b"one:x"), true),
328    ///     (Unknown(b"one".to_vec()), QName(b"x").into()),
329    /// );
330    /// ```
331    #[inline]
332    pub fn resolve<'n>(
333        &self,
334        name: QName<'n>,
335        attribute: bool,
336    ) -> (ResolveResult<'_>, LocalName<'n>) {
337        self.ns_resolver.resolve(name, !attribute)
338    }
339
340    /// Resolves a potentially qualified **element name** into
341    /// _(namespace name, local name)_.
342    ///
343    /// An unprefixed element name resolves to the current default namespace, if any.
344    /// This is a convenience for [`resolve(name, false)`](Self::resolve).
345    ///
346    /// # Example
347    ///
348    /// ```
349    /// use oxixml_xml::events::Event;
350    /// use oxixml_xml::name::{Namespace, ResolveResult::*};
351    /// use oxixml_xml::reader::NsReader;
352    ///
353    /// let mut reader = NsReader::from_str(r#"<tag xmlns="urn:d"/>"#);
354    /// if let Event::Empty(e) = reader.read_event().expect("empty") {
355    ///     assert_eq!(
356    ///         reader.resolve_element(e.name()),
357    ///         (Bound(Namespace(b"urn:d")), e.local_name()),
358    ///     );
359    /// }
360    /// ```
361    #[inline]
362    pub fn resolve_element<'n>(&self, name: QName<'n>) -> (ResolveResult<'_>, LocalName<'n>) {
363        self.ns_resolver.resolve_element(name)
364    }
365
366    /// Resolves a potentially qualified **attribute name** into
367    /// _(namespace name, local name)_.
368    ///
369    /// An unprefixed attribute name is never bound to the default namespace, so it
370    /// resolves to [`Unbound`](ResolveResult::Unbound). This is a convenience for
371    /// [`resolve(name, true)`](Self::resolve).
372    #[inline]
373    pub fn resolve_attribute<'n>(&self, name: QName<'n>) -> (ResolveResult<'_>, LocalName<'n>) {
374        self.ns_resolver.resolve_attribute(name)
375    }
376
377    /// Returns an iterator over the namespace bindings currently in scope, yielding
378    /// _(prefix, namespace)_ pairs. The reserved `xml` and `xmlns` bindings are not
379    /// included.
380    ///
381    /// # Example
382    ///
383    /// ```
384    /// use oxixml_xml::name::{Namespace, PrefixDeclaration};
385    /// use oxixml_xml::reader::NsReader;
386    ///
387    /// let mut reader = NsReader::from_str(r#"<tag xmlns="d" xmlns:a="a1"/>"#);
388    /// let _ = reader.read_event().expect("empty");
389    /// assert_eq!(reader.prefixes().collect::<Vec<_>>(), vec![
390    ///     (PrefixDeclaration::Default, Namespace(b"d")),
391    ///     (PrefixDeclaration::Named(b"a"), Namespace(b"a1")),
392    /// ]);
393    /// ```
394    #[inline]
395    pub fn prefixes(&self) -> NamespaceBindingsIter<'_> {
396        self.ns_resolver.bindings()
397    }
398}
399
400impl<R: BufRead> NsReader<R> {
401    /// Reads the next event into the given buffer.
402    ///
403    /// This method manages namespaces but doesn't resolve them automatically. You
404    /// should call [`resolve_element`](Self::resolve_element) if you want to get a
405    /// namespace.
406    ///
407    /// You can also use [`read_resolved_event_into`](Self::read_resolved_event_into)
408    /// instead if you want to resolve the namespace as soon as you get an event.
409    ///
410    /// # Examples
411    ///
412    /// ```
413    /// use oxixml_xml::events::Event;
414    /// use oxixml_xml::name::{Namespace, ResolveResult::*};
415    /// use oxixml_xml::reader::NsReader;
416    ///
417    /// let mut reader = NsReader::from_reader(r#"
418    ///     <x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
419    ///        <y:tag2><!--Test comment-->Test</y:tag2>
420    ///        <y:tag2>Test 2</y:tag2>
421    ///     </x:tag1>
422    /// "#.as_bytes());
423    /// reader.config_mut().trim_text(true);
424    ///
425    /// let mut count = 0;
426    /// let mut buf = Vec::new();
427    /// let mut txt = Vec::new();
428    /// loop {
429    ///     match reader.read_event_into(&mut buf).expect("valid event") {
430    ///         Event::Start(e) => {
431    ///             count += 1;
432    ///             let (ns, local) = reader.resolve_element(e.name());
433    ///             match local.as_ref() {
434    ///                 b"tag1" => assert_eq!(ns, Bound(Namespace(b"www.xxxx"))),
435    ///                 b"tag2" => assert_eq!(ns, Bound(Namespace(b"www.yyyy"))),
436    ///                 _ => unreachable!(),
437    ///             }
438    ///         }
439    ///         Event::Text(e) => txt.push(e.decode().expect("utf-8").into_owned()),
440    ///         Event::Eof => break,
441    ///         _ => (),
442    ///     }
443    ///     buf.clear();
444    /// }
445    /// assert_eq!(count, 3);
446    /// assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);
447    /// ```
448    #[inline]
449    pub fn read_event_into<'b>(&mut self, buf: &'b mut Vec<u8>) -> Result<Event<'b>> {
450        self.read_event_impl(buf)
451    }
452
453    /// Reads the next event into the given buffer and resolves its namespace (if
454    /// applicable).
455    ///
456    /// Namespace is resolved only for [`Start`](Event::Start),
457    /// [`Empty`](Event::Empty) and [`End`](Event::End) events. For all other events
458    /// the concept of a namespace is not defined, so a
459    /// [`ResolveResult::Unbound`] is returned.
460    ///
461    /// If you are not interested in namespaces, you can use
462    /// [`read_event_into`](Self::read_event_into) which will not automatically
463    /// resolve namespaces for you.
464    ///
465    /// # Examples
466    ///
467    /// ```
468    /// use oxixml_xml::events::Event;
469    /// use oxixml_xml::name::{Namespace, QName, ResolveResult::*};
470    /// use oxixml_xml::reader::NsReader;
471    ///
472    /// let mut reader = NsReader::from_reader(r#"
473    ///     <x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
474    ///        <y:tag2><!--Test comment-->Test</y:tag2>
475    ///     </x:tag1>
476    /// "#.as_bytes());
477    /// reader.config_mut().trim_text(true);
478    ///
479    /// let mut count = 0;
480    /// let mut buf = Vec::new();
481    /// loop {
482    ///     match reader.read_resolved_event_into(&mut buf).expect("valid event") {
483    ///         (Bound(Namespace(b"www.xxxx")), Event::Start(e)) => {
484    ///             count += 1;
485    ///             assert_eq!(e.local_name(), QName(b"tag1").into());
486    ///         }
487    ///         (Bound(Namespace(b"www.yyyy")), Event::Start(e)) => {
488    ///             count += 1;
489    ///             assert_eq!(e.local_name(), QName(b"tag2").into());
490    ///         }
491    ///         (_, Event::Start(_)) => unreachable!(),
492    ///         (_, Event::Eof) => break,
493    ///         _ => (),
494    ///     }
495    ///     buf.clear();
496    /// }
497    /// assert_eq!(count, 2);
498    /// ```
499    #[inline]
500    pub fn read_resolved_event_into<'b>(
501        &mut self,
502        buf: &'b mut Vec<u8>,
503    ) -> Result<(ResolveResult<'_>, Event<'b>)> {
504        let event = self.read_event_impl(buf)?;
505        Ok(self.ns_resolver.resolve_event(event))
506    }
507
508    /// Reads until the matching end element is found, using the provided buffer as
509    /// intermediate storage for events content. This function is supposed to be
510    /// called after you already read a [`Start`](Event::Start) event.
511    ///
512    /// Manages nested cases where parent and child elements have the _literally_
513    /// same name.
514    ///
515    /// If a corresponding [`End`](Event::End) event is not found, an error of type
516    /// [`Error::IllFormed`](crate::errors::Error::IllFormed) will be returned.
517    ///
518    /// The `end` parameter should contain the name of the end element _in the
519    /// reader encoding_. It is good practice to always get that parameter using
520    /// [`BytesStart::to_end()`](crate::events::BytesStart::to_end).
521    #[inline]
522    pub fn read_to_end_into(&mut self, end: QName, buf: &mut Vec<u8>) -> Result<Span> {
523        // According to https://www.w3.org/TR/xml11/#dt-etag the end name should
524        // match the start name literally. See `Config::check_end_names`.
525        let result = self.reader.read_to_end_into(end, buf)?;
526        // `read_to_end_into` consumed the closing tag. Because nobody can access
527        // its content anymore, we directly pop the opening tag's namespace scope.
528        self.ns_resolver.pop();
529        Ok(result)
530    }
531
532    /// Reads the content between start and end tags, including any markup, using the
533    /// provided buffer as intermediate storage for events content. This function is
534    /// supposed to be called after you already read a [`Start`](Event::Start) event.
535    ///
536    /// Manages nested cases where parent and child elements have the _literally_
537    /// same name.
538    ///
539    /// This method does not unescape read data, instead it returns content "as is".
540    #[inline]
541    pub fn read_text_into<'b>(
542        &mut self,
543        end: QName,
544        buf: &'b mut Vec<u8>,
545    ) -> Result<BytesText<'b>> {
546        let result = self.reader.read_text_into(end, buf)?;
547        // `read_text_into` consumed the closing tag, so pop its namespace scope.
548        self.ns_resolver.pop();
549        Ok(result)
550    }
551}
552
553impl NsReader<BufReader<File>> {
554    /// Creates an XML reader from a file path.
555    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
556        Ok(Self::new(Reader::from_file(path)?))
557    }
558}
559
560impl<'i> NsReader<&'i [u8]> {
561    /// Creates an XML reader from a string slice.
562    #[inline]
563    #[allow(clippy::should_implement_trait)]
564    pub fn from_str(s: &'i str) -> Self {
565        Self::new(Reader::from_str(s))
566    }
567
568    /// Reads the next event, borrowing its content from the input buffer.
569    ///
570    /// This method manages namespaces but doesn't resolve them automatically. You
571    /// should call [`resolve_element`](Self::resolve_element) if you want to get a
572    /// namespace.
573    ///
574    /// You can also use [`read_resolved_event`](Self::read_resolved_event) instead
575    /// if you want to resolve the namespace as soon as you get an event.
576    ///
577    /// # Examples
578    ///
579    /// ```
580    /// use oxixml_xml::events::Event;
581    /// use oxixml_xml::name::{Namespace, ResolveResult::*};
582    /// use oxixml_xml::reader::NsReader;
583    ///
584    /// let mut reader = NsReader::from_str(r#"
585    ///     <x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
586    ///        <y:tag2><!--Test comment-->Test</y:tag2>
587    ///        <y:tag2>Test 2</y:tag2>
588    ///     </x:tag1>
589    /// "#);
590    /// reader.config_mut().trim_text(true);
591    ///
592    /// let mut count = 0;
593    /// let mut txt = Vec::new();
594    /// loop {
595    ///     match reader.read_event().expect("valid event") {
596    ///         Event::Start(e) => {
597    ///             count += 1;
598    ///             let (ns, local) = reader.resolve_element(e.name());
599    ///             match local.as_ref() {
600    ///                 b"tag1" => assert_eq!(ns, Bound(Namespace(b"www.xxxx"))),
601    ///                 b"tag2" => assert_eq!(ns, Bound(Namespace(b"www.yyyy"))),
602    ///                 _ => unreachable!(),
603    ///             }
604    ///         }
605    ///         Event::Text(e) => txt.push(e.decode().expect("utf-8").into_owned()),
606    ///         Event::Eof => break,
607    ///         _ => (),
608    ///     }
609    /// }
610    /// assert_eq!(count, 3);
611    /// assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);
612    /// ```
613    #[inline]
614    pub fn read_event(&mut self) -> Result<Event<'i>> {
615        self.read_event_impl(())
616    }
617
618    /// Reads the next event, borrowing its content from the input buffer, and
619    /// resolves its namespace (if applicable).
620    ///
621    /// Namespace is resolved only for [`Start`](Event::Start),
622    /// [`Empty`](Event::Empty) and [`End`](Event::End) events. For all other events
623    /// the concept of a namespace is not defined, so a
624    /// [`ResolveResult::Unbound`] is returned.
625    ///
626    /// If you are not interested in namespaces, you can use
627    /// [`read_event`](Self::read_event) which will not automatically resolve
628    /// namespaces for you.
629    ///
630    /// # Examples
631    ///
632    /// ```
633    /// use oxixml_xml::events::Event;
634    /// use oxixml_xml::name::{Namespace, QName, ResolveResult::*};
635    /// use oxixml_xml::reader::NsReader;
636    ///
637    /// let mut reader = NsReader::from_str(r#"
638    ///     <x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
639    ///        <y:tag2><!--Test comment-->Test</y:tag2>
640    ///     </x:tag1>
641    /// "#);
642    /// reader.config_mut().trim_text(true);
643    ///
644    /// let mut count = 0;
645    /// loop {
646    ///     match reader.read_resolved_event().expect("valid event") {
647    ///         (Bound(Namespace(b"www.xxxx")), Event::Start(e)) => {
648    ///             count += 1;
649    ///             assert_eq!(e.local_name(), QName(b"tag1").into());
650    ///         }
651    ///         (Bound(Namespace(b"www.yyyy")), Event::Start(e)) => {
652    ///             count += 1;
653    ///             assert_eq!(e.local_name(), QName(b"tag2").into());
654    ///         }
655    ///         (_, Event::Start(_)) => unreachable!(),
656    ///         (_, Event::Eof) => break,
657    ///         _ => (),
658    ///     }
659    /// }
660    /// assert_eq!(count, 2);
661    /// ```
662    #[inline]
663    pub fn read_resolved_event(&mut self) -> Result<(ResolveResult<'_>, Event<'i>)> {
664        let event = self.read_event_impl(())?;
665        Ok(self.ns_resolver.resolve_event(event))
666    }
667
668    /// Reads until the matching end element is found. This function is supposed to
669    /// be called after you already read a [`Start`](Event::Start) event.
670    ///
671    /// Returns a span that covers the content between `>` of an opening tag and `<`
672    /// of a closing tag.
673    ///
674    /// Manages nested cases where parent and child elements have the _literally_
675    /// same name.
676    ///
677    /// # Examples
678    ///
679    /// ```
680    /// use oxixml_xml::events::{BytesStart, Event};
681    /// use oxixml_xml::name::{Namespace, ResolveResult};
682    /// use oxixml_xml::reader::NsReader;
683    ///
684    /// let mut reader = NsReader::from_str(r#"
685    ///     <outer xmlns="namespace 1">
686    ///         <inner xmlns="namespace 2">
687    ///             <outer></outer>
688    ///         </inner>
689    ///         <inner>
690    ///             <inner></inner>
691    ///             <inner/>
692    ///             <outer></outer>
693    ///             <p:outer xmlns:p="ns"></p:outer>
694    ///             <outer/>
695    ///         </inner>
696    ///     </outer>
697    /// "#);
698    /// reader.config_mut().trim_text(true);
699    ///
700    /// let ns = Namespace(b"namespace 1");
701    /// let start = BytesStart::from_content(r#"outer xmlns="namespace 1""#, 5);
702    /// let end   = start.to_end().into_owned();
703    ///
704    /// assert_eq!(
705    ///     reader.read_resolved_event().expect("start"),
706    ///     (ResolveResult::Bound(ns), Event::Start(start))
707    /// );
708    ///
709    /// // Skip all events to the corresponding end event, handling nested <outer>s.
710    /// reader.read_to_end(end.name()).expect("end");
711    ///
712    /// assert_eq!(
713    ///     reader.read_resolved_event().expect("eof"),
714    ///     (ResolveResult::Unbound, Event::Eof)
715    /// );
716    /// ```
717    #[inline]
718    pub fn read_to_end(&mut self, end: QName) -> Result<Span> {
719        let result = self.reader.read_to_end(end)?;
720        self.ns_resolver.pop();
721        Ok(result)
722    }
723
724    /// Reads content between start and end tags, including any markup. This function
725    /// is supposed to be called after you already read a [`Start`](Event::Start)
726    /// event.
727    ///
728    /// Manages nested cases where parent and child elements have the _literally_
729    /// same name.
730    ///
731    /// This method does not unescape read data, instead it returns content "as is".
732    #[inline]
733    pub fn read_text(&mut self, end: QName) -> Result<BytesText<'i>> {
734        let result = self.reader.read_text(end)?;
735        self.ns_resolver.pop();
736        Ok(result)
737    }
738}
739
740impl<R> Deref for NsReader<R> {
741    type Target = Reader<R>;
742
743    #[inline]
744    fn deref(&self) -> &Self::Target {
745        &self.reader
746    }
747}
748
749#[cfg(test)]
750mod tests;