1use quick_xml::events::{BytesStart, Event};
4use quick_xml::{Reader, Writer};
5
6use crate::error::Result;
7
8pub fn capture_element(reader: &mut Reader<&[u8]>, start: &BytesStart) -> Result<Vec<u8>> {
12 let mut writer = Writer::new(Vec::new());
13
14 writer.write_event(Event::Start(start.to_owned()))?;
16
17 let tag_name = start.name().as_ref().to_vec();
19 let mut depth = 1u32;
20 let mut buf = Vec::new();
21
22 loop {
23 match reader.read_event_into(&mut buf) {
24 Ok(Event::Start(ref e)) => {
25 if e.name().as_ref() == tag_name {
26 depth += 1;
27 }
28 writer.write_event(Event::Start(e.to_owned()))?;
29 }
30 Ok(Event::End(ref e)) => {
31 if e.name().as_ref() == tag_name {
32 depth -= 1;
33 }
34 writer.write_event(Event::End(e.to_owned()))?;
35 if depth == 0 {
36 break;
37 }
38 }
39 Ok(Event::Empty(ref e)) => {
40 writer.write_event(Event::Empty(e.to_owned()))?;
41 }
42 Ok(Event::Text(ref e)) => {
43 writer.write_event(Event::Text(e.to_owned().into_owned()))?;
44 }
45 Ok(Event::CData(ref e)) => {
46 writer.write_event(Event::CData(e.to_owned().into_owned()))?;
47 }
48 Ok(Event::Comment(ref e)) => {
49 writer.write_event(Event::Comment(e.to_owned().into_owned()))?;
50 }
51 Ok(Event::PI(ref e)) => {
52 writer.write_event(Event::PI(e.to_owned().into_owned()))?;
53 }
54 Ok(Event::Decl(ref e)) => {
55 writer.write_event(Event::Decl(e.to_owned().into_owned()))?;
56 }
57 Ok(Event::DocType(ref e)) => {
58 writer.write_event(Event::DocType(e.to_owned().into_owned()))?;
59 }
60 Ok(Event::GeneralRef(ref e)) => {
63 writer.write_event(Event::GeneralRef(e.to_owned().into_owned()))?;
64 }
65 Ok(Event::Eof) => break,
66 Err(e) => return Err(e.into()),
67 }
68 buf.clear();
69 }
70
71 Ok(writer.into_inner())
72}
73
74pub fn capture_empty_element(e: &BytesStart) -> Result<Vec<u8>> {
76 let mut writer = Writer::new(Vec::new());
77 writer.write_event(Event::Empty(e.to_owned()))?;
78 Ok(writer.into_inner())
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn capture_simple_element() {
87 let xml = r#"<root><child>text</child><sibling/></root>"#;
88 let mut reader = Reader::from_str(xml);
89 reader.config_mut().trim_text(true);
90 let mut buf = Vec::new();
91
92 loop {
94 match reader.read_event_into(&mut buf) {
95 Ok(Event::Start(ref e)) if e.name().as_ref() == b"child" => {
96 let captured = capture_element(&mut reader, e).unwrap();
97 let s = String::from_utf8(captured).unwrap();
98 assert!(s.contains("<child>"));
99 assert!(s.contains("text"));
100 assert!(s.contains("</child>"));
101 return;
102 }
103 _ => {}
104 }
105 buf.clear();
106 }
107 }
108
109 #[test]
110 fn capture_empty() {
111 let xml = r#"<item attr="val"/>"#;
112 let mut reader = Reader::from_str(xml);
113 reader.config_mut().trim_text(true);
114 let mut buf = Vec::new();
115
116 loop {
117 if let Ok(Event::Empty(ref e)) = reader.read_event_into(&mut buf) {
118 let captured = capture_empty_element(e).unwrap();
119 let s = String::from_utf8(captured).unwrap();
120 assert!(s.contains("item"));
121 assert!(s.contains("attr"));
122 return;
123 }
124 buf.clear();
125 }
126 }
127
128 #[test]
129 fn capture_nested_element() {
130 let xml = r#"<outer><inner><deep>data</deep></inner></outer>"#;
131 let mut reader = Reader::from_str(xml);
132 reader.config_mut().trim_text(true);
133 let mut buf = Vec::new();
134
135 loop {
136 match reader.read_event_into(&mut buf) {
137 Ok(Event::Start(ref e)) if e.name().as_ref() == b"outer" => {
138 let captured = capture_element(&mut reader, e).unwrap();
139 let s = String::from_utf8(captured).unwrap();
140 assert!(s.contains("<outer>"));
141 assert!(s.contains("<inner>"));
142 assert!(s.contains("<deep>"));
143 assert!(s.contains("data"));
144 assert!(s.contains("</deep>"));
145 assert!(s.contains("</inner>"));
146 assert!(s.contains("</outer>"));
147 return;
148 }
149 _ => {}
150 }
151 buf.clear();
152 }
153 }
154
155 #[test]
156 fn unmodelled_subtree_is_preserved_byte_for_byte() {
157 let xml = br#"<root><x:item x:id="7"><x:child>one & two</x:child><!--note--></x:item></root>"#;
158 let mut reader = Reader::from_reader(xml.as_slice());
159 let mut buf = Vec::new();
160
161 loop {
162 match reader.read_event_into(&mut buf) {
163 Ok(Event::Start(ref e)) if e.name().as_ref() == b"x:item" => {
164 assert_eq!(
165 capture_element(&mut reader, e).unwrap(),
166 br#"<x:item x:id="7"><x:child>one & two</x:child><!--note--></x:item>"#
167 );
168 return;
169 }
170 Ok(Event::Eof) => panic!("no unmodelled subtree"),
171 _ => {}
172 }
173 buf.clear();
174 }
175 }
176}