xml_log_scan/
lib.rs

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
18/// Filter and print XMLs.
19pub 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}