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;