use minidom::{Node, Element}; pub trait NamespaceAwareCompare { /// Namespace-aware comparison for tests fn compare_to(&self, other: &Self) -> bool; } impl NamespaceAwareCompare for Node { fn compare_to(&self, other: &Self) -> bool { match (self, other) { (&Node::Element(ref elem1), &Node::Element(ref elem2)) => Element::compare_to(elem1, elem2), (&Node::Text(ref text1), &Node::Text(ref text2)) => text1 == text2, _ => false, } } } impl NamespaceAwareCompare for Element { fn compare_to(&self, other: &Self) -> bool { if self.name() == other.name() && self.ns() == other.ns() && self.attrs().eq(other.attrs()) { let child_elems = self.children().count(); let text_is_whitespace = self.texts() .all(|text| text.chars().all(char::is_whitespace)); if child_elems > 0 && text_is_whitespace { // Ignore all the whitespace text nodes self.children().zip(other.children()) .all(|(node1, node2)| node1.compare_to(node2)) } else { // Compare with text nodes self.nodes().zip(other.nodes()) .all(|(node1, node2)| node1.compare_to(node2)) } } else { false } } } #[cfg(test)] mod tests { use super::*; use minidom::Element; #[test] fn simple() { let elem1: Element = "x 3".parse().unwrap(); let elem2: Element = "x 3".parse().unwrap(); assert!(elem1.compare_to(&elem2)); } #[test] fn wrong_attr_name() { let elem1: Element = "x 3".parse().unwrap(); let elem2: Element = "x 3".parse().unwrap(); assert!(!elem1.compare_to(&elem2)); } #[test] fn wrong_attr_value() { let elem1: Element = "x 3".parse().unwrap(); let elem2: Element = "x 3".parse().unwrap(); assert!(!elem1.compare_to(&elem2)); } #[test] fn attr_order() { let elem1: Element = "".parse().unwrap(); let elem2: Element = "".parse().unwrap(); assert!(elem1.compare_to(&elem2)); } #[test] fn wrong_texts() { let elem1: Element = "foo".parse().unwrap(); let elem2: Element = "bar".parse().unwrap(); assert!(!elem1.compare_to(&elem2)); } #[test] fn children() { let elem1: Element = "".parse().unwrap(); let elem2: Element = "".parse().unwrap(); assert!(elem1.compare_to(&elem2)); } #[test] fn wrong_children() { let elem1: Element = "".parse().unwrap(); let elem2: Element = "".parse().unwrap(); assert!(!elem1.compare_to(&elem2)); } #[test] fn xmlns_wrong() { let elem1: Element = "".parse().unwrap(); let elem2: Element = "".parse().unwrap(); assert!(!elem1.compare_to(&elem2)); } #[test] fn xmlns_other_prefix() { let elem1: Element = "".parse().unwrap(); let elem2: Element = "".parse().unwrap(); assert!(elem1.compare_to(&elem2)); } #[test] fn xmlns_dup() { let elem1: Element = "".parse().unwrap(); let elem2: Element = "".parse().unwrap(); assert!(elem1.compare_to(&elem2)); } }