1use quick_xml::events::Event;
2use quick_xml::Reader;
3use std::collections::HashSet;
4
5pub mod xpath;
6
7pub fn paths(path: &str) -> Result<Vec<String>, Box<dyn std::error::Error>> {
9 let mut reader = Reader::from_file(path)?;
10 let mut xpath: xpath::XPath = xpath::XPath::new();
11 let mut buf = Vec::new();
12 let mut xpath_strings = HashSet::new();
13 loop {
14 match reader.read_event(&mut buf) {
15 Ok(Event::Start(ref e)) => {
16 xpath.push(xpath::start_tag_string(e)?);
17 }
18 Ok(Event::End(ref e)) => {
19 xpath.pop_checked(xpath::end_tag_string(e)?);
20 }
21 Ok(Event::Eof) => break,
22 Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
23 _ => (),
24 }
25 xpath_strings.insert(xpath.as_string());
26 }
27 let mut xpath_strings: Vec<String> = xpath_strings.into_iter().collect();
28 xpath_strings.sort();
29 Ok(xpath_strings)
30}
31
32#[cfg(test)]
33mod tests {
34 use super::*;
35
36 #[test]
37 fn test_paths() {
38 let paths = paths("example_data/notes.xml").unwrap();
39 assert_eq!(
40 paths,
41 vec![
42 "/",
43 "/notes",
44 "/notes/note",
45 "/notes/note/body",
46 "/notes/note/from",
47 "/notes/note/heading",
48 "/notes/note/to"
49 ]
50 );
51 }
52}