1#![doc = include_str!("../README.md")]
2#![warn(
3 missing_docs,
4 missing_debug_implementations,
5 missing_copy_implementations,
6 trivial_casts,
7 trivial_numeric_casts,
8 unused_extern_crates,
9 unused_import_braces,
10 unused_qualifications,
11 variant_size_differences
12)]
13
14use std::io::{BufRead, Cursor, Read};
15
16use quick_xml::{Reader, Writer, events::Event};
17
18pub fn filter_xmls(mut input: impl BufRead, xpath: Option<&str>) {
20 let mut buffer = [0u8; 1024];
21 while let Ok(count) = input.read(&mut buffer) {
22 if count == 0 {
23 break;
24 }
25
26 let mut head = &buffer[..count];
27
28 while let Some(pos) = head.iter().position(|&n| n == b'<') {
29 head = &head[pos..];
30
31 let cursor = Cursor::new(head);
32
33 let xml_candidate = cursor.chain(input);
34
35 let mut reader = Reader::from_reader(xml_candidate);
36
37 let mut buf = Vec::new();
38
39 let events = match reader.read_event_into(&mut buf) {
40 Ok(Event::Start(ref b)) => {
41 let (start, end) = (b.clone().into_owned(), b.to_end().into_owned());
42
43 let end = end.name();
44
45 let mut depth = 0;
46 let mut events = vec![Event::Start(start)];
47
48 loop {
49 let evt = reader.read_event_into(&mut buf);
50
51 if let Ok(e) = &evt {
52 events.push(e.clone().into_owned());
53 }
54
55 match evt {
56 Ok(Event::Start(ref e)) if e.name() == end => depth += 1,
57 Ok(Event::End(ref e)) if e.name() == end => {
58 if depth == 0 {
59 break Ok(events);
60 }
61 depth -= 1;
62 }
63 Ok(Event::Eof) | Err(_) => break Err(()),
64 _ => (),
65 }
66 }
67 }
68 Ok(e @ Event::Empty(_)) => Ok(vec![e.clone().into_owned()]),
69 _ => Err(()),
70 };
71
72 if let Ok(events) = events {
73 let mut writer = Writer::new(Cursor::new(Vec::new()));
74 for event in events {
75 writer.write_event(event).expect("write event");
76 }
77 let buf = writer.into_inner().into_inner();
78 let xml = String::from_utf8_lossy(&buf);
79 if let Some(xpath) = xpath {
80 use amxml::dom::*;
81 let doc = new_document(&xml).expect("well formed XML");
82 let root = doc.root_element();
83 let result = root.eval_xpath(xpath).expect("XPath expression");
84 if result.len() > 0 {
85 println!("{}", result.to_string());
86 }
87 } else {
88 println!("{xml}");
89 }
90 }
91
92 let (cursor, remaining_input) = reader.into_inner().into_inner();
93
94 input = remaining_input;
95
96 if (cursor.position() as usize) < head.len() {
97 head = &head[cursor.position() as usize..];
98 } else {
99 break;
100 }
101 }
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 #[test]
108 fn it_works() {
109 assert_eq!(2 + 2, 4);
110 }
111}