1//! A reader that manages namespace declarations found in the input and able
2//! to resolve [qualified names] to [expanded names].
3//!
4//! [qualified names]: https://www.w3.org/TR/xml-names11/#dt-qualname
5//! [expanded names]: https://www.w3.org/TR/xml-names11/#dt-expname
6
7use std::borrow::Cow;
8use std::fs::File;
9use std::io::{BufRead, BufReader};
10use std::ops::Deref;
11use std::path::Path;
12
13use crate::errors::Result;
14use crate::events::Event;
15use crate::name::{LocalName, NamespaceResolver, QName, ResolveResult};
16use crate::reader::{Reader, Span, XmlSource};
17
18/// A low level encoding-agnostic XML event reader that performs namespace resolution.
19///
20/// Consumes a [`BufRead`] and streams XML `Event`s.
21pub struct NsReader<R> {
22 /// An XML reader
23 pub(super) reader: Reader<R>,
24 /// Buffer that contains names of namespace prefixes (the part between `xmlns:`
25 /// and an `=`) and namespace values.
26 buffer: Vec<u8>,
27 /// A buffer to manage namespaces
28 ns_resolver: NamespaceResolver,
29 /// We cannot pop data from the namespace stack until returned `Empty` or `End`
30 /// event will be processed by the user, so we only mark that we should that
31 /// in the next [`Self::read_event_impl()`] call.
32 pending_pop: bool,
33}
34
35/// Builder methods
36impl<R> NsReader<R> {
37 /// Creates a `NsReader` that reads from a reader.
38 #[inline]
39 pub fn from_reader(reader: R) -> Self {
40 Self::new(Reader::from_reader(reader))
41 }
42
43 configure_methods!(reader);
44}
45
46/// Private methods
47impl<R> NsReader<R> {
48 #[inline]
49 fn new(reader: Reader<R>) -> Self {
50 Self {
51 reader,
52 buffer: Vec::new(),
53 ns_resolver: NamespaceResolver::default(),
54 pending_pop: false,
55 }
56 }
57
58 fn read_event_impl<'i, B>(&mut self, buf: B) -> Result<Event<'i>>
59 where
60 R: XmlSource<'i, B>,
61 {
62 self.pop();
63 let event = self.reader.read_event_impl(buf);
64 self.process_event(event)
65 }
66
67 pub(super) fn pop(&mut self) {
68 if self.pending_pop {
69 self.ns_resolver.pop(&mut self.buffer);
70 self.pending_pop = false;
71 }
72 }
73
74 pub(super) fn process_event<'i>(&mut self, event: Result<Event<'i>>) -> Result<Event<'i>> {
75 match event {
76 Ok(Event::Start(e)) => {
77 self.ns_resolver.push(&e, &mut self.buffer);
78 Ok(Event::Start(e))
79 }
80 Ok(Event::Empty(e)) => {
81 self.ns_resolver.push(&e, &mut self.buffer);
82 // notify next `read_event_impl()` invocation that it needs to pop this
83 // namespace scope
84 self.pending_pop = true;
85 Ok(Event::Empty(e))
86 }
87 Ok(Event::End(e)) => {
88 // notify next `read_event_impl()` invocation that it needs to pop this
89 // namespace scope
90 self.pending_pop = true;
91 Ok(Event::End(e))
92 }
93 e => e,
94 }
95 }
96
97 pub(super) fn resolve_event<'i>(
98 &mut self,
99 event: Result<Event<'i>>,
100 ) -> Result<(ResolveResult, Event<'i>)> {
101 match event {
102 Ok(Event::Start(e)) => Ok((
103 self.ns_resolver.find(e.name(), &self.buffer),
104 Event::Start(e),
105 )),
106 Ok(Event::Empty(e)) => Ok((
107 self.ns_resolver.find(e.name(), &self.buffer),
108 Event::Empty(e),
109 )),
110 Ok(Event::End(e)) => Ok((
111 // Comment that prevent cargo rmt
112 self.ns_resolver.find(e.name(), &self.buffer),
113 Event::End(e),
114 )),
115 Ok(e) => Ok((ResolveResult::Unbound, e)),
116 Err(e) => Err(e),
117 }
118 }
119}
120
121/// Getters
122impl<R> NsReader<R> {
123 /// Consumes `NsReader` returning the underlying reader
124 ///
125 /// See the [`Reader::into_inner`] for examples
126 #[inline]
127 pub fn into_inner(self) -> R {
128 self.reader.into_inner()
129 }
130
131 /// Gets a mutable reference to the underlying reader.
132 pub fn get_mut(&mut self) -> &mut R {
133 self.reader.get_mut()
134 }
135
136 /// Resolves a potentially qualified **element name** or **attribute name**
137 /// into _(namespace name, local name)_.
138 ///
139 /// _Qualified_ names have the form `prefix:local-name` where the `prefix`
140 /// is defined on any containing XML element via `xmlns:prefix="the:namespace:uri"`.
141 /// The namespace prefix can be defined on the same element as the name in question.
142 ///
143 /// The method returns following results depending on the `name` shape,
144 /// `attribute` flag and the presence of the default namespace:
145 ///
146 /// |attribute|`xmlns="..."`|QName |ResolveResult |LocalName
147 /// |---------|-------------|-------------------|-----------------------|------------
148 /// |`true` |Not defined |`local-name` |[`Unbound`] |`local-name`
149 /// |`true` |Defined |`local-name` |[`Unbound`] |`local-name`
150 /// |`true` |_any_ |`prefix:local-name`|[`Bound`] / [`Unknown`]|`local-name`
151 /// |`false` |Not defined |`local-name` |[`Unbound`] |`local-name`
152 /// |`false` |Defined |`local-name` |[`Bound`] (default) |`local-name`
153 /// |`false` |_any_ |`prefix:local-name`|[`Bound`] / [`Unknown`]|`local-name`
154 ///
155 /// If you want to clearly indicate that name that you resolve is an element
156 /// or an attribute name, you could use [`resolve_attribute()`] or [`resolve_element()`]
157 /// methods.
158 ///
159 /// # Lifetimes
160 ///
161 /// - `'n`: lifetime of a name. Returned local name will be bound to the same
162 /// lifetime as the name in question.
163 /// - returned namespace name will be bound to the reader itself
164 ///
165 /// [`Bound`]: ResolveResult::Bound
166 /// [`Unbound`]: ResolveResult::Unbound
167 /// [`Unknown`]: ResolveResult::Unknown
168 /// [`resolve_attribute()`]: Self::resolve_attribute()
169 /// [`resolve_element()`]: Self::resolve_element()
170 #[inline]
171 pub fn resolve<'n>(&self, name: QName<'n>, attribute: bool) -> (ResolveResult, LocalName<'n>) {
172 self.ns_resolver.resolve(name, &self.buffer, !attribute)
173 }
174
175 /// Resolves a potentially qualified **element name** into _(namespace name, local name)_.
176 ///
177 /// _Qualified_ element names have the form `prefix:local-name` where the
178 /// `prefix` is defined on any containing XML element via `xmlns:prefix="the:namespace:uri"`.
179 /// The namespace prefix can be defined on the same element as the element
180 /// in question.
181 ///
182 /// _Unqualified_ elements inherits the current _default namespace_.
183 ///
184 /// The method returns following results depending on the `name` shape and
185 /// the presence of the default namespace:
186 ///
187 /// |`xmlns="..."`|QName |ResolveResult |LocalName
188 /// |-------------|-------------------|-----------------------|------------
189 /// |Not defined |`local-name` |[`Unbound`] |`local-name`
190 /// |Defined |`local-name` |[`Bound`] (default) |`local-name`
191 /// |_any_ |`prefix:local-name`|[`Bound`] / [`Unknown`]|`local-name`
192 ///
193 /// # Lifetimes
194 ///
195 /// - `'n`: lifetime of an element name. Returned local name will be bound
196 /// to the same lifetime as the name in question.
197 /// - returned namespace name will be bound to the reader itself
198 ///
199 /// # Examples
200 ///
201 /// This example shows how you can resolve qualified name into a namespace.
202 /// Note, that in the code like this you do not need to do that manually,
203 /// because the namespace resolution result returned by the [`read_resolved_event()`].
204 ///
205 /// ```
206 /// # use pretty_assertions::assert_eq;
207 /// use quick_xml::events::Event;
208 /// use quick_xml::name::{Namespace, QName, ResolveResult::*};
209 /// use quick_xml::reader::NsReader;
210 ///
211 /// let mut reader = NsReader::from_str("<tag xmlns='root namespace'/>");
212 ///
213 /// match reader.read_event().unwrap() {
214 /// Event::Empty(e) => assert_eq!(
215 /// reader.resolve_element(e.name()),
216 /// (Bound(Namespace(b"root namespace")), QName(b"tag").into())
217 /// ),
218 /// _ => unreachable!(),
219 /// }
220 /// ```
221 ///
222 /// [`Bound`]: ResolveResult::Bound
223 /// [`Unbound`]: ResolveResult::Unbound
224 /// [`Unknown`]: ResolveResult::Unknown
225 /// [`read_resolved_event()`]: Self::read_resolved_event
226 #[inline]
227 pub fn resolve_element<'n>(&self, name: QName<'n>) -> (ResolveResult, LocalName<'n>) {
228 self.ns_resolver.resolve(name, &self.buffer, true)
229 }
230
231 /// Resolves a potentially qualified **attribute name** into _(namespace name, local name)_.
232 ///
233 /// _Qualified_ attribute names have the form `prefix:local-name` where the
234 /// `prefix` is defined on any containing XML element via `xmlns:prefix="the:namespace:uri"`.
235 /// The namespace prefix can be defined on the same element as the attribute
236 /// in question.
237 ///
238 /// _Unqualified_ attribute names do *not* inherit the current _default namespace_.
239 ///
240 /// The method returns following results depending on the `name` shape and
241 /// the presence of the default namespace:
242 ///
243 /// |`xmlns="..."`|QName |ResolveResult |LocalName
244 /// |-------------|-------------------|-----------------------|------------
245 /// |Not defined |`local-name` |[`Unbound`] |`local-name`
246 /// |Defined |`local-name` |[`Unbound`] |`local-name`
247 /// |_any_ |`prefix:local-name`|[`Bound`] / [`Unknown`]|`local-name`
248 ///
249 /// # Lifetimes
250 ///
251 /// - `'n`: lifetime of an attribute name. Returned local name will be bound
252 /// to the same lifetime as the name in question.
253 /// - returned namespace name will be bound to the reader itself
254 ///
255 /// # Examples
256 ///
257 /// ```
258 /// # use pretty_assertions::assert_eq;
259 /// use quick_xml::events::Event;
260 /// use quick_xml::events::attributes::Attribute;
261 /// use quick_xml::name::{Namespace, QName, ResolveResult::*};
262 /// use quick_xml::reader::NsReader;
263 ///
264 /// let mut reader = NsReader::from_str("
265 /// <tag one='1'
266 /// p:two='2'
267 /// xmlns='root namespace'
268 /// xmlns:p='other namespace'/>
269 /// ");
270 /// reader.trim_text(true);
271 ///
272 /// match reader.read_event().unwrap() {
273 /// Event::Empty(e) => {
274 /// let mut iter = e.attributes();
275 ///
276 /// // Unlike elements, attributes without explicit namespace
277 /// // not bound to any namespace
278 /// let one = iter.next().unwrap().unwrap();
279 /// assert_eq!(
280 /// reader.resolve_attribute(one.key),
281 /// (Unbound, QName(b"one").into())
282 /// );
283 ///
284 /// let two = iter.next().unwrap().unwrap();
285 /// assert_eq!(
286 /// reader.resolve_attribute(two.key),
287 /// (Bound(Namespace(b"other namespace")), QName(b"two").into())
288 /// );
289 /// }
290 /// _ => unreachable!(),
291 /// }
292 /// ```
293 ///
294 /// [`Bound`]: ResolveResult::Bound
295 /// [`Unbound`]: ResolveResult::Unbound
296 /// [`Unknown`]: ResolveResult::Unknown
297 #[inline]
298 pub fn resolve_attribute<'n>(&self, name: QName<'n>) -> (ResolveResult, LocalName<'n>) {
299 self.ns_resolver.resolve(name, &self.buffer, false)
300 }
301}
302
303impl<R: BufRead> NsReader<R> {
304 /// Reads the next event into given buffer.
305 ///
306 /// This method manages namespaces but doesn't resolve them automatically.
307 /// You should call [`resolve_element()`] if you want to get a namespace.
308 ///
309 /// You also can use [`read_resolved_event_into()`] instead if you want to resolve
310 /// namespace as soon as you get an event.
311 ///
312 /// # Examples
313 ///
314 /// ```
315 /// # use pretty_assertions::assert_eq;
316 /// use quick_xml::events::Event;
317 /// use quick_xml::name::{Namespace, ResolveResult::*};
318 /// use quick_xml::reader::NsReader;
319 ///
320 /// let mut reader = NsReader::from_str(r#"
321 /// <x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
322 /// <y:tag2><!--Test comment-->Test</y:tag2>
323 /// <y:tag2>Test 2</y:tag2>
324 /// </x:tag1>
325 /// "#);
326 /// reader.trim_text(true);
327 ///
328 /// let mut count = 0;
329 /// let mut buf = Vec::new();
330 /// let mut txt = Vec::new();
331 /// loop {
332 /// match reader.read_event_into(&mut buf).unwrap() {
333 /// Event::Start(e) => {
334 /// count += 1;
335 /// let (ns, local) = reader.resolve_element(e.name());
336 /// match local.as_ref() {
337 /// b"tag1" => assert_eq!(ns, Bound(Namespace(b"www.xxxx"))),
338 /// b"tag2" => assert_eq!(ns, Bound(Namespace(b"www.yyyy"))),
339 /// _ => unreachable!(),
340 /// }
341 /// }
342 /// Event::Text(e) => {
343 /// txt.push(e.unescape().unwrap().into_owned())
344 /// }
345 /// Event::Eof => break,
346 /// _ => (),
347 /// }
348 /// buf.clear();
349 /// }
350 /// assert_eq!(count, 3);
351 /// assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);
352 /// ```
353 ///
354 /// [`resolve_element()`]: Self::resolve_element
355 /// [`read_resolved_event_into()`]: Self::read_resolved_event_into
356 #[inline]
357 pub fn read_event_into<'b>(&mut self, buf: &'b mut Vec<u8>) -> Result<Event<'b>> {
358 self.read_event_impl(buf)
359 }
360
361 /// Reads the next event into given buffer and resolves its namespace (if applicable).
362 ///
363 /// Namespace is resolved only for [`Start`], [`Empty`] and [`End`] events.
364 /// For all other events the concept of namespace is not defined, so
365 /// a [`ResolveResult::Unbound`] is returned.
366 ///
367 /// If you are not interested in namespaces, you can use [`read_event_into()`]
368 /// which will not automatically resolve namespaces for you.
369 ///
370 /// # Examples
371 ///
372 /// ```
373 /// # use pretty_assertions::assert_eq;
374 /// use quick_xml::events::Event;
375 /// use quick_xml::name::{Namespace, QName, ResolveResult::*};
376 /// use quick_xml::reader::NsReader;
377 ///
378 /// let mut reader = NsReader::from_str(r#"
379 /// <x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
380 /// <y:tag2><!--Test comment-->Test</y:tag2>
381 /// <y:tag2>Test 2</y:tag2>
382 /// </x:tag1>
383 /// "#);
384 /// reader.trim_text(true);
385 ///
386 /// let mut count = 0;
387 /// let mut buf = Vec::new();
388 /// let mut txt = Vec::new();
389 /// loop {
390 /// match reader.read_resolved_event_into(&mut buf).unwrap() {
391 /// (Bound(Namespace(b"www.xxxx")), Event::Start(e)) => {
392 /// count += 1;
393 /// assert_eq!(e.local_name(), QName(b"tag1").into());
394 /// }
395 /// (Bound(Namespace(b"www.yyyy")), Event::Start(e)) => {
396 /// count += 1;
397 /// assert_eq!(e.local_name(), QName(b"tag2").into());
398 /// }
399 /// (_, Event::Start(_)) => unreachable!(),
400 ///
401 /// (_, Event::Text(e)) => {
402 /// txt.push(e.unescape().unwrap().into_owned())
403 /// }
404 /// (_, Event::Eof) => break,
405 /// _ => (),
406 /// }
407 /// buf.clear();
408 /// }
409 /// assert_eq!(count, 3);
410 /// assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);
411 /// ```
412 ///
413 /// [`Start`]: Event::Start
414 /// [`Empty`]: Event::Empty
415 /// [`End`]: Event::End
416 /// [`read_event_into()`]: Self::read_event_into
417 #[inline]
418 pub fn read_resolved_event_into<'b>(
419 &mut self,
420 buf: &'b mut Vec<u8>,
421 ) -> Result<(ResolveResult, Event<'b>)> {
422 let event = self.read_event_impl(buf);
423 self.resolve_event(event)
424 }
425
426 /// Reads until end element is found using provided buffer as intermediate
427 /// storage for events content. This function is supposed to be called after
428 /// you already read a [`Start`] event.
429 ///
430 /// Returns a span that cover content between `>` of an opening tag and `<` of
431 /// a closing tag or an empty slice, if [`expand_empty_elements`] is set and
432 /// this method was called after reading expanded [`Start`] event.
433 ///
434 /// Manages nested cases where parent and child elements have the _literally_
435 /// same name.
436 ///
437 /// If corresponding [`End`] event will not be found, the [`UnexpectedEof`]
438 /// will be returned. In particularly, that error will be returned if you call
439 /// this method without consuming the corresponding [`Start`] event first.
440 ///
441 /// If your reader created from a string slice or byte array slice, it is
442 /// better to use [`read_to_end()`] method, because it will not copy bytes
443 /// into intermediate buffer.
444 ///
445 /// The provided `buf` buffer will be filled only by one event content at time.
446 /// Before reading of each event the buffer will be cleared. If you know an
447 /// appropriate size of each event, you can preallocate the buffer to reduce
448 /// number of reallocations.
449 ///
450 /// The `end` parameter should contain name of the end element _in the reader
451 /// encoding_. It is good practice to always get that parameter using
452 /// [`BytesStart::to_end()`] method.
453 ///
454 /// # Namespaces
455 ///
456 /// While the `NsReader` does namespace resolution, namespaces does not
457 /// change the algorithm for comparing names. Although the names `a:name`
458 /// and `b:name` where both prefixes `a` and `b` resolves to the same namespace,
459 /// are semantically equivalent, `</b:name>` cannot close `<a:name>`, because
460 /// according to [the specification]
461 ///
462 /// > The end of every element that begins with a **start-tag** MUST be marked
463 /// > by an **end-tag** containing a name that echoes the element's type as
464 /// > given in the **start-tag**
465 ///
466 /// # Examples
467 ///
468 /// This example shows, how you can skip XML content after you read the
469 /// start event.
470 ///
471 /// ```
472 /// # use pretty_assertions::assert_eq;
473 /// use quick_xml::events::{BytesStart, Event};
474 /// use quick_xml::name::{Namespace, ResolveResult};
475 /// use quick_xml::reader::NsReader;
476 ///
477 /// let mut reader = NsReader::from_str(r#"
478 /// <outer xmlns="namespace 1">
479 /// <inner xmlns="namespace 2">
480 /// <outer></outer>
481 /// </inner>
482 /// <inner>
483 /// <inner></inner>
484 /// <inner/>
485 /// <outer></outer>
486 /// <p:outer xmlns:p="ns"></p:outer>
487 /// <outer/>
488 /// </inner>
489 /// </outer>
490 /// "#);
491 /// reader.trim_text(true);
492 /// let mut buf = Vec::new();
493 ///
494 /// let ns = Namespace(b"namespace 1");
495 /// let start = BytesStart::from_content(r#"outer xmlns="namespace 1""#, 5);
496 /// let end = start.to_end().into_owned();
497 ///
498 /// // First, we read a start event...
499 /// assert_eq!(
500 /// reader.read_resolved_event_into(&mut buf).unwrap(),
501 /// (ResolveResult::Bound(ns), Event::Start(start))
502 /// );
503 ///
504 /// // ...then, we could skip all events to the corresponding end event.
505 /// // This call will correctly handle nested <outer> elements.
506 /// // Note, however, that this method does not handle namespaces.
507 /// reader.read_to_end_into(end.name(), &mut buf).unwrap();
508 ///
509 /// // At the end we should get an Eof event, because we ate the whole XML
510 /// assert_eq!(
511 /// reader.read_resolved_event_into(&mut buf).unwrap(),
512 /// (ResolveResult::Unbound, Event::Eof)
513 /// );
514 /// ```
515 ///
516 /// [`Start`]: Event::Start
517 /// [`End`]: Event::End
518 /// [`UnexpectedEof`]: crate::errors::Error::UnexpectedEof
519 /// [`read_to_end()`]: Self::read_to_end
520 /// [`BytesStart::to_end()`]: crate::events::BytesStart::to_end
521 /// [`expand_empty_elements`]: Self::expand_empty_elements
522 /// [the specification]: https://www.w3.org/TR/xml11/#dt-etag
523 #[inline]
524 pub fn read_to_end_into(&mut self, end: QName, buf: &mut Vec<u8>) -> Result<Span> {
525 // According to the https://www.w3.org/TR/xml11/#dt-etag, end name should
526 // match literally the start name. See `Self::check_end_names` documentation
527 self.reader.read_to_end_into(end, buf)
528 }
529}
530
531impl NsReader<BufReader<File>> {
532 /// Creates an XML reader from a file path.
533 pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
534 Ok(Self::new(Reader::from_file(path)?))
535 }
536}
537
538impl<'i> NsReader<&'i [u8]> {
539 /// Creates an XML reader from a string slice.
540 #[inline]
541 #[allow(clippy::should_implement_trait)]
542 pub fn from_str(s: &'i str) -> Self {
543 Self::new(Reader::from_str(s))
544 }
545
546 /// Reads the next event, borrow its content from the input buffer.
547 ///
548 /// This method manages namespaces but doesn't resolve them automatically.
549 /// You should call [`resolve_element()`] if you want to get a namespace.
550 ///
551 /// You also can use [`read_resolved_event()`] instead if you want to resolve namespace
552 /// as soon as you get an event.
553 ///
554 /// There is no asynchronous `read_event_async()` version of this function,
555 /// because it is not necessary -- the contents are already in memory and no IO
556 /// is needed, therefore there is no potential for blocking.
557 ///
558 /// # Examples
559 ///
560 /// ```
561 /// # use pretty_assertions::assert_eq;
562 /// use quick_xml::events::Event;
563 /// use quick_xml::name::{Namespace, ResolveResult::*};
564 /// use quick_xml::reader::NsReader;
565 ///
566 /// let mut reader = NsReader::from_str(r#"
567 /// <x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
568 /// <y:tag2><!--Test comment-->Test</y:tag2>
569 /// <y:tag2>Test 2</y:tag2>
570 /// </x:tag1>
571 /// "#);
572 /// reader.trim_text(true);
573 ///
574 /// let mut count = 0;
575 /// let mut txt = Vec::new();
576 /// loop {
577 /// match reader.read_event().unwrap() {
578 /// Event::Start(e) => {
579 /// count += 1;
580 /// let (ns, local) = reader.resolve_element(e.name());
581 /// match local.as_ref() {
582 /// b"tag1" => assert_eq!(ns, Bound(Namespace(b"www.xxxx"))),
583 /// b"tag2" => assert_eq!(ns, Bound(Namespace(b"www.yyyy"))),
584 /// _ => unreachable!(),
585 /// }
586 /// }
587 /// Event::Text(e) => {
588 /// txt.push(e.unescape().unwrap().into_owned())
589 /// }
590 /// Event::Eof => break,
591 /// _ => (),
592 /// }
593 /// }
594 /// assert_eq!(count, 3);
595 /// assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);
596 /// ```
597 ///
598 /// [`resolve_element()`]: Self::resolve_element
599 /// [`read_resolved_event()`]: Self::read_resolved_event
600 #[inline]
601 pub fn read_event(&mut self) -> Result<Event<'i>> {
602 self.read_event_impl(())
603 }
604
605 /// Reads the next event, borrow its content from the input buffer, and resolves
606 /// its namespace (if applicable).
607 ///
608 /// Namespace is resolved only for [`Start`], [`Empty`] and [`End`] events.
609 /// For all other events the concept of namespace is not defined, so
610 /// a [`ResolveResult::Unbound`] is returned.
611 ///
612 /// If you are not interested in namespaces, you can use [`read_event()`]
613 /// which will not automatically resolve namespaces for you.
614 ///
615 /// There is no asynchronous `read_resolved_event_async()` version of this function,
616 /// because it is not necessary -- the contents are already in memory and no IO
617 /// is needed, therefore there is no potential for blocking.
618 ///
619 /// # Examples
620 ///
621 /// ```
622 /// # use pretty_assertions::assert_eq;
623 /// use quick_xml::events::Event;
624 /// use quick_xml::name::{Namespace, QName, ResolveResult::*};
625 /// use quick_xml::reader::NsReader;
626 ///
627 /// let mut reader = NsReader::from_str(r#"
628 /// <x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
629 /// <y:tag2><!--Test comment-->Test</y:tag2>
630 /// <y:tag2>Test 2</y:tag2>
631 /// </x:tag1>
632 /// "#);
633 /// reader.trim_text(true);
634 ///
635 /// let mut count = 0;
636 /// let mut txt = Vec::new();
637 /// loop {
638 /// match reader.read_resolved_event().unwrap() {
639 /// (Bound(Namespace(b"www.xxxx")), Event::Start(e)) => {
640 /// count += 1;
641 /// assert_eq!(e.local_name(), QName(b"tag1").into());
642 /// }
643 /// (Bound(Namespace(b"www.yyyy")), Event::Start(e)) => {
644 /// count += 1;
645 /// assert_eq!(e.local_name(), QName(b"tag2").into());
646 /// }
647 /// (_, Event::Start(_)) => unreachable!(),
648 ///
649 /// (_, Event::Text(e)) => {
650 /// txt.push(e.unescape().unwrap().into_owned())
651 /// }
652 /// (_, Event::Eof) => break,
653 /// _ => (),
654 /// }
655 /// }
656 /// assert_eq!(count, 3);
657 /// assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);
658 /// ```
659 ///
660 /// [`Start`]: Event::Start
661 /// [`Empty`]: Event::Empty
662 /// [`End`]: Event::End
663 /// [`read_event()`]: Self::read_event
664 #[inline]
665 pub fn read_resolved_event(&mut self) -> Result<(ResolveResult, Event<'i>)> {
666 let event = self.read_event_impl(());
667 self.resolve_event(event)
668 }
669
670 /// Reads until end element is found. This function is supposed to be called
671 /// after you already read a [`Start`] event.
672 ///
673 /// Returns a span that cover content between `>` of an opening tag and `<` of
674 /// a closing tag or an empty slice, if [`expand_empty_elements`] is set and
675 /// this method was called after reading expanded [`Start`] event.
676 ///
677 /// Manages nested cases where parent and child elements have the _literally_
678 /// same name.
679 ///
680 /// If corresponding [`End`] event will not be found, the [`UnexpectedEof`]
681 /// will be returned. In particularly, that error will be returned if you call
682 /// this method without consuming the corresponding [`Start`] event first.
683 ///
684 /// The `end` parameter should contain name of the end element _in the reader
685 /// encoding_. It is good practice to always get that parameter using
686 /// [`BytesStart::to_end()`] method.
687 ///
688 /// There is no asynchronous `read_to_end_async()` version of this function,
689 /// because it is not necessary -- the contents are already in memory and no IO
690 /// is needed, therefore there is no potential for blocking.
691 ///
692 /// # Namespaces
693 ///
694 /// While the `NsReader` does namespace resolution, namespaces does not
695 /// change the algorithm for comparing names. Although the names `a:name`
696 /// and `b:name` where both prefixes `a` and `b` resolves to the same namespace,
697 /// are semantically equivalent, `</b:name>` cannot close `<a:name>`, because
698 /// according to [the specification]
699 ///
700 /// > The end of every element that begins with a **start-tag** MUST be marked
701 /// > by an **end-tag** containing a name that echoes the element's type as
702 /// > given in the **start-tag**
703 ///
704 /// # Examples
705 ///
706 /// This example shows, how you can skip XML content after you read the
707 /// start event.
708 ///
709 /// ```
710 /// # use pretty_assertions::assert_eq;
711 /// use quick_xml::events::{BytesStart, Event};
712 /// use quick_xml::name::{Namespace, ResolveResult};
713 /// use quick_xml::reader::NsReader;
714 ///
715 /// let mut reader = NsReader::from_str(r#"
716 /// <outer xmlns="namespace 1">
717 /// <inner xmlns="namespace 2">
718 /// <outer></outer>
719 /// </inner>
720 /// <inner>
721 /// <inner></inner>
722 /// <inner/>
723 /// <outer></outer>
724 /// <p:outer xmlns:p="ns"></p:outer>
725 /// <outer/>
726 /// </inner>
727 /// </outer>
728 /// "#);
729 /// reader.trim_text(true);
730 ///
731 /// let ns = Namespace(b"namespace 1");
732 /// let start = BytesStart::from_content(r#"outer xmlns="namespace 1""#, 5);
733 /// let end = start.to_end().into_owned();
734 ///
735 /// // First, we read a start event...
736 /// assert_eq!(
737 /// reader.read_resolved_event().unwrap(),
738 /// (ResolveResult::Bound(ns), Event::Start(start))
739 /// );
740 ///
741 /// // ...then, we could skip all events to the corresponding end event.
742 /// // This call will correctly handle nested <outer> elements.
743 /// // Note, however, that this method does not handle namespaces.
744 /// reader.read_to_end(end.name()).unwrap();
745 ///
746 /// // At the end we should get an Eof event, because we ate the whole XML
747 /// assert_eq!(
748 /// reader.read_resolved_event().unwrap(),
749 /// (ResolveResult::Unbound, Event::Eof)
750 /// );
751 /// ```
752 ///
753 /// [`Start`]: Event::Start
754 /// [`End`]: Event::End
755 /// [`UnexpectedEof`]: crate::errors::Error::UnexpectedEof
756 /// [`BytesStart::to_end()`]: crate::events::BytesStart::to_end
757 /// [`expand_empty_elements`]: Self::expand_empty_elements
758 /// [the specification]: https://www.w3.org/TR/xml11/#dt-etag
759 #[inline]
760 pub fn read_to_end(&mut self, end: QName) -> Result<Span> {
761 // According to the https://www.w3.org/TR/xml11/#dt-etag, end name should
762 // match literally the start name. See `Self::check_end_names` documentation
763 self.reader.read_to_end(end)
764 }
765
766 /// Reads content between start and end tags, including any markup. This
767 /// function is supposed to be called after you already read a [`Start`] event.
768 ///
769 /// Manages nested cases where parent and child elements have the _literally_
770 /// same name.
771 ///
772 /// This method does not unescape read data, instead it returns content
773 /// "as is" of the XML document. This is because it has no idea what text
774 /// it reads, and if, for example, it contains CDATA section, attempt to
775 /// unescape it content will spoil data.
776 ///
777 /// Any text will be decoded using the XML current [`decoder()`].
778 ///
779 /// Actually, this method perform the following code:
780 ///
781 /// ```ignore
782 /// let span = reader.read_to_end(end)?;
783 /// let text = reader.decoder().decode(&reader.inner_slice[span]);
784 /// ```
785 ///
786 /// # Examples
787 ///
788 /// This example shows, how you can read a HTML content from your XML document.
789 ///
790 /// ```
791 /// # use pretty_assertions::assert_eq;
792 /// # use std::borrow::Cow;
793 /// use quick_xml::events::{BytesStart, Event};
794 /// use quick_xml::reader::NsReader;
795 ///
796 /// let mut reader = NsReader::from_str(r#"
797 /// <html>
798 /// <title>This is a HTML text</title>
799 /// <p>Usual XML rules does not apply inside it
800 /// <p>For example, elements not needed to be &quot;closed&quot;
801 /// </html>
802 /// "#);
803 /// reader.trim_text(true);
804 ///
805 /// let start = BytesStart::new("html");
806 /// let end = start.to_end().into_owned();
807 ///
808 /// // First, we read a start event...
809 /// assert_eq!(reader.read_event().unwrap(), Event::Start(start));
810 /// // ...and disable checking of end names because we expect HTML further...
811 /// reader.check_end_names(false);
812 ///
813 /// // ...then, we could read text content until close tag.
814 /// // This call will correctly handle nested <html> elements.
815 /// let text = reader.read_text(end.name()).unwrap();
816 /// assert_eq!(text, Cow::Borrowed(r#"
817 /// <title>This is a HTML text</title>
818 /// <p>Usual XML rules does not apply inside it
819 /// <p>For example, elements not needed to be &quot;closed&quot;
820 /// "#));
821 ///
822 /// // Now we can enable checks again
823 /// reader.check_end_names(true);
824 ///
825 /// // At the end we should get an Eof event, because we ate the whole XML
826 /// assert_eq!(reader.read_event().unwrap(), Event::Eof);
827 /// ```
828 ///
829 /// [`Start`]: Event::Start
830 /// [`decoder()`]: Reader::decoder()
831 #[inline]
832 pub fn read_text(&mut self, end: QName) -> Result<Cow<'i, str>> {
833 self.reader.read_text(end)
834 }
835}
836
837impl<R> Deref for NsReader<R> {
838 type Target = Reader<R>;
839
840 #[inline]
841 fn deref(&self) -> &Self::Target {
842 &self.reader
843 }
844}
845