docx_rs/reader/
numberings.rs1use std::io::Read;
2use xml::reader::{EventReader, XmlEvent};
3
4use super::*;
5use crate::reader::{FromXML, ReaderError};
6
7use std::str::FromStr;
8
9impl FromXML for Numberings {
10 fn from_xml<R: Read>(reader: R) -> Result<Self, ReaderError> {
11 let mut parser = EventReader::new(reader);
12 let mut nums = Self::default();
13 loop {
14 let e = parser.next();
15 match e {
16 Ok(XmlEvent::StartElement {
17 attributes, name, ..
18 }) => {
19 let e = XMLElement::from_str(&name.local_name).unwrap();
20 match e {
21 XMLElement::AbstractNumbering => {
22 let mut id = 0;
23 for a in attributes {
24 let local_name = &a.name.local_name;
25 if local_name == "abstractNumId" {
26 id = usize::from_str(&a.value)?;
27 }
28 }
29 let mut abs_num = AbstractNumbering::new(id);
30 loop {
31 let e = parser.next();
32 match e {
33 Ok(XmlEvent::StartElement {
34 attributes, name, ..
35 }) => {
36 let e = XMLElement::from_str(&name.local_name).unwrap();
37 match e {
38 XMLElement::Level => {
39 let l = Level::read(&mut parser, &attributes)?;
40 abs_num = abs_num.add_level(l);
41 }
42 XMLElement::StyleLink => {
43 abs_num = abs_num.style_link(&attributes[0].value)
44 }
45 XMLElement::NumStyleLink => {
46 abs_num =
47 abs_num.num_style_link(&attributes[0].value)
48 }
49 _ => {}
50 }
51 }
52 Ok(XmlEvent::EndElement { name, .. }) => {
53 let e = XMLElement::from_str(&name.local_name).unwrap();
54 if let XMLElement::AbstractNumbering = e {
55 nums = nums.add_abstract_numbering(abs_num);
56 break;
57 }
58 }
59 _ => {}
60 }
61 }
62 continue;
63 }
64 XMLElement::Num => {
65 let mut id = 0;
66 for a in attributes {
67 let local_name = &a.name.local_name;
68 if local_name == "numId" {
69 id = usize::from_str(&a.value)?;
70 }
71 }
72 let mut abs_num_id = 0;
73 let mut level_overrides = vec![];
74
75 loop {
76 let e = parser.next();
77 match e {
78 Ok(XmlEvent::StartElement {
79 attributes, name, ..
80 }) => {
81 let e = XMLElement::from_str(&name.local_name).unwrap();
82 match e {
83 XMLElement::AbstractNumberingId => {
84 abs_num_id = usize::from_str(&attributes[0].value)?
85 }
86 XMLElement::LvlOverride => {
87 if let Ok(o) =
88 LevelOverride::read(&mut parser, &attributes)
89 {
90 level_overrides.push(o);
91 }
92 }
93 _ => {}
94 }
95 }
96 Ok(XmlEvent::EndElement { name, .. }) => {
97 let e = XMLElement::from_str(&name.local_name).unwrap();
98 if let XMLElement::Num = e {
99 let num = Numbering::new(id, abs_num_id);
100 nums =
101 nums.add_numbering(num.overrides(level_overrides));
102 break;
103 }
104 }
105 _ => {}
106 }
107 }
108 continue;
109 }
110 _ => {}
111 }
112 }
113 Ok(XmlEvent::EndElement { name, .. }) => {
114 let e = XMLElement::from_str(&name.local_name).unwrap();
115 if let XMLElement::Numbering = e {
116 break;
117 }
118 }
119 Ok(XmlEvent::EndDocument { .. }) => break,
120 Err(_) => return Err(ReaderError::XMLReadError),
121 _ => {}
122 }
123 }
124 Ok(nums)
125 }
126}
127
128#[cfg(test)]
129mod tests {
130
131 use super::*;
132 use crate::types::*;
133 #[cfg(test)]
134 use pretty_assertions::assert_eq;
135
136 #[test]
137 fn test_numberings_from_xml() {
138 let xml = r#"<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
139 xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" >
140 <w:abstractNum w:abstractNumId="0" w15:restartNumberingAfterBreak="0">
141 <w:multiLevelType w:val="hybridMultilevel"></w:multiLevelType>
142 <w:lvl w:ilvl="0" w15:tentative="1">
143 <w:start w:val="1"></w:start>
144 <w:numFmt w:val="bullet"></w:numFmt>
145 <w:lvlText w:val="●"></w:lvlText>
146 <w:lvlJc w:val="left"></w:lvlJc>
147 <w:pPr>
148 <w:ind w:left="720" w:hanging="360"></w:ind>
149 </w:pPr>
150 <w:rPr></w:rPr>
151 </w:lvl>
152 </w:abstractNum>
153 <w:num w:numId="1">
154 <w:abstractNumId w:val="0"></w:abstractNumId>
155 </w:num>
156</w:numbering>"#;
157 let n = Numberings::from_xml(xml.as_bytes()).unwrap();
158 let mut nums = Numberings::new();
159 nums = nums
160 .add_abstract_numbering(
161 AbstractNumbering::new(0).add_level(
162 Level::new(
163 0,
164 Start::new(1),
165 NumberFormat::new("bullet"),
166 LevelText::new("●"),
167 LevelJc::new("left"),
168 )
169 .indent(
170 Some(720),
171 Some(SpecialIndentType::Hanging(360)),
172 None,
173 None,
174 ),
175 ),
176 )
177 .add_numbering(Numbering::new(1, 0));
178 assert_eq!(n, nums)
179 }
180
181 #[test]
182 fn test_numberings_from_xml_with_num_style_link() {
183 let xml = r#"<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
184 xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" >
185 <w:abstractNum w:abstractNumId="0">
186 <w:multiLevelType w:val="hybridMultilevel"/>
187 <w:numStyleLink w:val="style1"/>
188 </w:abstractNum>
189 <w:num w:numId="1">
190 <w:abstractNumId w:val="0"></w:abstractNumId>
191 </w:num>
192</w:numbering>"#;
193 let n = Numberings::from_xml(xml.as_bytes()).unwrap();
194 let mut nums = Numberings::new();
195 nums = nums
196 .add_abstract_numbering(AbstractNumbering::new(0).num_style_link("style1"))
197 .add_numbering(Numbering::new(1, 0));
198 assert_eq!(n, nums)
199 }
200
201 #[test]
202 fn test_numberings_from_xml_with_style_link() {
203 let xml = r#"<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
204 xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" >
205 <w:abstractNum w:abstractNumId="0">
206 <w:multiLevelType w:val="hybridMultilevel"/>
207 <w:styleLink w:val="style1"/>
208 </w:abstractNum>
209 <w:num w:numId="1">
210 <w:abstractNumId w:val="0"></w:abstractNumId>
211 </w:num>
212</w:numbering>"#;
213 let n = Numberings::from_xml(xml.as_bytes()).unwrap();
214 let mut nums = Numberings::new();
215 nums = nums
216 .add_abstract_numbering(AbstractNumbering::new(0).style_link("style1"))
217 .add_numbering(Numbering::new(1, 0));
218 assert_eq!(n, nums)
219 }
220
221 #[test]
222 fn test_numberings_from_xml_with_override() {
223 let xml = r#"<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
224 xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" >
225 <w:abstractNum w:abstractNumId="0">
226 <w:multiLevelType w:val="hybridMultilevel"/>
227 </w:abstractNum>
228 <w:num w:numId="1">
229 <w:abstractNumId w:val="0"></w:abstractNumId>
230 <w:lvlOverride w:ilvl="0">
231 <w:startOverride w:val="1"/>
232 </w:lvlOverride>
233 <w:lvlOverride w:ilvl="1">
234 <w:startOverride w:val="1"/>
235 </w:lvlOverride>
236 </w:num>
237</w:numbering>"#;
238 let n = Numberings::from_xml(xml.as_bytes()).unwrap();
239 let mut nums = Numberings::new();
240 let overrides = vec![
241 LevelOverride::new(0).start(1),
242 LevelOverride::new(1).start(1),
243 ];
244 let num = Numbering::new(1, 0).overrides(overrides);
245 nums = nums
246 .add_abstract_numbering(AbstractNumbering::new(0))
247 .add_numbering(num);
248 assert_eq!(n, nums)
249 }
250}