use std::io::Read; use xml::reader::{EventReader, XmlEvent}; use super::*; use crate::reader::{FromXML, ReaderError}; use std::str::FromStr; impl FromXML for Numberings { fn from_xml(reader: R) -> Result { let mut parser = EventReader::new(reader); let mut nums = Self::default(); loop { let e = parser.next(); match e { Ok(XmlEvent::StartElement { attributes, name, .. }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); match e { XMLElement::AbstractNumbering => { let mut id = 0; for a in attributes { let local_name = &a.name.local_name; if local_name == "abstractNumId" { id = usize::from_str(&a.value)?; } } let mut abs_num = AbstractNumbering::new(id); loop { let e = parser.next(); match e { Ok(XmlEvent::StartElement { attributes, name, .. }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); match e { XMLElement::Level => { let l = Level::read(&mut parser, &attributes)?; abs_num = abs_num.add_level(l); } XMLElement::StyleLink => { abs_num = abs_num.style_link(&attributes[0].value) } XMLElement::NumStyleLink => { abs_num = abs_num.num_style_link(&attributes[0].value) } _ => {} } } Ok(XmlEvent::EndElement { name, .. }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); if let XMLElement::AbstractNumbering = e { nums = nums.add_abstract_numbering(abs_num); break; } } _ => {} } } continue; } XMLElement::Num => { let mut id = 0; for a in attributes { let local_name = &a.name.local_name; if local_name == "numId" { id = usize::from_str(&a.value)?; } } let mut abs_num_id = 0; loop { let e = parser.next(); match e { Ok(XmlEvent::StartElement { attributes, name, .. }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); if let XMLElement::AbstractNumberingId = e { abs_num_id = usize::from_str(&attributes[0].value)?; } } Ok(XmlEvent::EndElement { name, .. }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); if let XMLElement::Num = e { nums = nums.add_numbering(Numbering::new(id, abs_num_id)); break; } } _ => {} } } continue; } _ => {} } } Ok(XmlEvent::EndElement { name, .. }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); if let XMLElement::Numbering = e { break; } } Ok(XmlEvent::EndDocument { .. }) => break, Err(_) => return Err(ReaderError::XMLReadError), _ => {} } } Ok(nums) } } #[cfg(test)] mod tests { use super::*; use crate::types::*; #[cfg(test)] use pretty_assertions::assert_eq; #[test] fn test_numberings_from_xml() { let xml = r#" "#; let n = Numberings::from_xml(xml.as_bytes()).unwrap(); let mut nums = Numberings::new(); nums = nums .add_abstract_numbering( AbstractNumbering::new(0).add_level( Level::new( 0, Start::new(1), NumberFormat::new("bullet"), LevelText::new("●"), LevelJc::new("left"), ) .indent( Some(720), Some(SpecialIndentType::Hanging(360)), None, None, ), ), ) .add_numbering(Numbering::new(1, 0)); assert_eq!(n, nums) } #[test] fn test_numberings_from_xml_with_num_style_link() { let xml = r#" "#; let n = Numberings::from_xml(xml.as_bytes()).unwrap(); let mut nums = Numberings::new(); nums = nums .add_abstract_numbering(AbstractNumbering::new(0).num_style_link("style1")) .add_numbering(Numbering::new(1, 0)); assert_eq!(n, nums) } #[test] fn test_numberings_from_xml_with_style_link() { let xml = r#" "#; let n = Numberings::from_xml(xml.as_bytes()).unwrap(); let mut nums = Numberings::new(); nums = nums .add_abstract_numbering(AbstractNumbering::new(0).style_link("style1")) .add_numbering(Numbering::new(1, 0)); assert_eq!(n, nums) } }