@@ -607,12 +607,91 @@ impl<R: BufRead> Reader<R> {
607607 }
608608 }
609609
610- /// Reads until end element is found
610+ /// Reads until end element is found using provided buffer as intermediate
611+ /// storage for events content. This function is supposed to be called after
612+ /// you already read a [`Start`] event.
611613 ///
612- /// Manages nested cases where parent and child elements have the same name
614+ /// Manages nested cases where parent and child elements have the same name.
615+ ///
616+ /// If corresponding [`End`] event will not be found, the [`Error::UnexpectedEof`]
617+ /// will be returned. In particularly, that error will be returned if you call
618+ /// this method without consuming the corresponding [`Start`] event first.
619+ ///
620+ /// If your reader created from a string slice or byte array slice, it is
621+ /// better to use [`read_to_end()`] method, because it will not copy bytes
622+ /// into intermediate buffer.
623+ ///
624+ /// The provided `buf` buffer will be filled only by one event content at time.
625+ /// Before reading of each event the buffer will be cleared. If you know an
626+ /// appropriate size of each event, you can preallocate the buffer to reduce
627+ /// number of reallocations.
628+ ///
629+ /// The `end` parameter should contain name of the end element _in the reader
630+ /// encoding_. It is good practice to always get that parameter using
631+ /// [`BytesStart::to_end()`] method.
632+ ///
633+ /// The correctness of the skipped events does not checked, if you disabled
634+ /// the [`check_end_names`] option.
635+ ///
636+ /// # Namespaces
637+ ///
638+ /// While the [`Reader`] does not support namespace resolution, namespaces
639+ /// does not change the algorithm for comparing names. Although the names
640+ /// `a:name` and `b:name` where both prefixes `a` and `b` resolves to the
641+ /// same namespace, are semantically equivalent, `</b:name>` cannot close
642+ /// `<a:name>`, because according to [the specification]
643+ ///
644+ /// > The end of every element that begins with a **start-tag** MUST be marked
645+ /// > by an **end-tag** containing a name that echoes the element's type as
646+ /// > given in the **start-tag**
647+ ///
648+ /// # Examples
649+ ///
650+ /// This example shows, how you can skip XML content after you read the
651+ /// start event.
652+ ///
653+ /// ```
654+ /// # use pretty_assertions::assert_eq;
655+ /// use quick_xml::events::{BytesStart, Event};
656+ /// use quick_xml::Reader;
657+ ///
658+ /// let mut reader = Reader::from_str(r#"
659+ /// <outer>
660+ /// <inner>
661+ /// <inner></inner>
662+ /// <inner/>
663+ /// <outer></outer>
664+ /// <outer/>
665+ /// </inner>
666+ /// </outer>
667+ /// "#);
668+ /// reader.trim_text(true);
669+ /// let mut buf = Vec::new();
670+ ///
671+ /// let start = BytesStart::borrowed_name(b"outer");
672+ /// let end = start.to_end().into_owned();
673+ ///
674+ /// // First, we read a start event...
675+ /// assert_eq!(reader.read_event_into(&mut buf).unwrap(), Event::Start(start));
676+ ///
677+ /// //...then, we could skip all events to the corresponding end event.
678+ /// // This call will correctly handle nested <outer> elements.
679+ /// // Note, however, that this method does not handle namespaces.
680+ /// reader.read_to_end_into(end.name(), &mut buf).unwrap();
681+ ///
682+ /// // At the end we should get an Eof event, because we ate the whole XML
683+ /// assert_eq!(reader.read_event_into(&mut buf).unwrap(), Event::Eof);
684+ /// ```
685+ ///
686+ /// [`Start`]: Event::Start
687+ /// [`End`]: Event::End
688+ /// [`read_to_end()`]: Self::read_to_end
689+ /// [`check_end_names`]: Self::check_end_names
690+ /// [the specification]: https://www.w3.org/TR/xml11/#dt-etag
613691 pub fn read_to_end_into ( & mut self , end : QName , buf : & mut Vec < u8 > ) -> Result < ( ) > {
614692 let mut depth = 0 ;
615693 loop {
694+ buf. clear ( ) ;
616695 match self . read_event_into ( buf) {
617696 Err ( e) => return Err ( e) ,
618697
@@ -629,7 +708,6 @@ impl<R: BufRead> Reader<R> {
629708 }
630709 _ => ( ) ,
631710 }
632- buf. clear ( ) ;
633711 }
634712 }
635713
@@ -974,9 +1052,75 @@ impl<'a> Reader<&'a [u8]> {
9741052 self . read_event_impl ( ( ) )
9751053 }
9761054
977- /// Reads until end element is found
1055+ /// Reads until end element is found. This function is supposed to be called
1056+ /// after you already read a [`Start`] event.
1057+ ///
1058+ /// Manages nested cases where parent and child elements have the same name.
1059+ ///
1060+ /// If corresponding [`End`] event will not be found, the [`Error::UnexpectedEof`]
1061+ /// will be returned. In particularly, that error will be returned if you call
1062+ /// this method without consuming the corresponding [`Start`] event first.
1063+ ///
1064+ /// The `end` parameter should contain name of the end element _in the reader
1065+ /// encoding_. It is good practice to always get that parameter using
1066+ /// [`BytesStart::to_end()`] method.
1067+ ///
1068+ /// The correctness of the skipped events does not checked, if you disabled
1069+ /// the [`check_end_names`] option.
1070+ ///
1071+ /// # Namespaces
1072+ ///
1073+ /// While the [`Reader`] does not support namespace resolution, namespaces
1074+ /// does not change the algorithm for comparing names. Although the names
1075+ /// `a:name` and `b:name` where both prefixes `a` and `b` resolves to the
1076+ /// same namespace, are semantically equivalent, `</b:name>` cannot close
1077+ /// `<a:name>`, because according to [the specification]
1078+ ///
1079+ /// > The end of every element that begins with a **start-tag** MUST be marked
1080+ /// > by an **end-tag** containing a name that echoes the element's type as
1081+ /// > given in the **start-tag**
1082+ ///
1083+ /// # Examples
1084+ ///
1085+ /// This example shows, how you can skip XML content after you read the
1086+ /// start event.
9781087 ///
979- /// Manages nested cases where parent and child elements have the same name
1088+ /// ```
1089+ /// # use pretty_assertions::assert_eq;
1090+ /// use quick_xml::events::{BytesStart, Event};
1091+ /// use quick_xml::Reader;
1092+ ///
1093+ /// let mut reader = Reader::from_str(r#"
1094+ /// <outer>
1095+ /// <inner>
1096+ /// <inner></inner>
1097+ /// <inner/>
1098+ /// <outer></outer>
1099+ /// <outer/>
1100+ /// </inner>
1101+ /// </outer>
1102+ /// "#);
1103+ /// reader.trim_text(true);
1104+ ///
1105+ /// let start = BytesStart::borrowed_name(b"outer");
1106+ /// let end = start.to_end().into_owned();
1107+ ///
1108+ /// // First, we read a start event...
1109+ /// assert_eq!(reader.read_event().unwrap(), Event::Start(start));
1110+ ///
1111+ /// //...then, we could skip all events to the corresponding end event.
1112+ /// // This call will correctly handle nested <outer> elements.
1113+ /// // Note, however, that this method does not handle namespaces.
1114+ /// reader.read_to_end(end.name()).unwrap();
1115+ ///
1116+ /// // At the end we should get an Eof event, because we ate the whole XML
1117+ /// assert_eq!(reader.read_event().unwrap(), Event::Eof);
1118+ /// ```
1119+ ///
1120+ /// [`Start`]: Event::Start
1121+ /// [`End`]: Event::End
1122+ /// [`check_end_names`]: Self::check_end_names
1123+ /// [the specification]: https://www.w3.org/TR/xml11/#dt-etag
9801124 pub fn read_to_end ( & mut self , end : QName ) -> Result < ( ) > {
9811125 let mut depth = 0 ;
9821126 loop {
0 commit comments