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