use std::io::Read; use std::str::FromStr; use xml::attribute::OwnedAttribute; use xml::reader::{EventReader, XmlEvent}; use super::*; use crate::types::*; impl ElementReader for TableCell { fn read(r: &mut EventReader, _: &[OwnedAttribute]) -> Result { let mut cell = TableCell::new(); loop { let e = r.next(); match e { Ok(XmlEvent::StartElement { attributes, name, .. }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); match e { XMLElement::Paragraph => { let p = Paragraph::read(r, &attributes)?; cell = cell.add_paragraph(p); continue; } XMLElement::TableCellProperty => loop { let e = r.next(); match e { Ok(XmlEvent::StartElement { attributes, name, .. }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); match e { XMLElement::TableCellWidth => { let mut w = 0; let mut width_type = WidthType::Auto; for a in attributes { let local_name = &a.name.local_name; if local_name == "type" { width_type = WidthType::from_str(&a.value)?; } else if local_name == "w" { w = usize::from_str(&a.value)?; } } cell = cell.width(w, width_type); } XMLElement::TableGridSpan => { if let Some(a) = &attributes.get(0) { cell = cell.grid_span(usize::from_str(&a.value)?) } } XMLElement::TableVMerge => { if let Some(a) = &attributes.get(0) { cell = cell.vertical_merge(VMergeType::from_str( &a.value, )?); } else { // Treat as a continue without attribute cell = cell.vertical_merge(VMergeType::Continue) } } XMLElement::VAlign => { if let Some(a) = &attributes.get(0) { cell = cell.vertical_align(VAlignType::from_str( &a.value, )?); } } XMLElement::TableCellBorders => { let borders = TableCellBorders::read(r, &attributes)?; cell = cell.set_borders(borders); } _ => {} } } Ok(XmlEvent::EndElement { name, .. }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); if e == XMLElement::TableCellProperty { break; } } Err(_) => return Err(ReaderError::XMLReadError), _ => {} } }, _ => {} } } Ok(XmlEvent::EndElement { name, .. }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); if e == XMLElement::TableCell { return Ok(cell); } } Err(_) => return Err(ReaderError::XMLReadError), _ => {} } } } } #[cfg(test)] mod tests { use super::*; #[cfg(test)] use pretty_assertions::assert_eq; #[test] fn test_read_cell_with_prop() { let c = r#" "#; let mut parser = EventReader::new(c.as_bytes()); let cell = TableCell::read(&mut parser, &[]).unwrap(); assert_eq!( cell, TableCell::new() .add_paragraph(Paragraph::new().add_run(Run::new())) .width(6425, WidthType::DXA) .grid_span(2) .vertical_merge(VMergeType::Restart) .set_border(TableCellBorder::new(BorderPosition::Top)) .set_border(TableCellBorder::new(BorderPosition::Left).size(3)) .set_border( TableCellBorder::new(BorderPosition::Bottom) .size(4) .border_type(BorderType::Double) ) .set_border( TableCellBorder::new(BorderPosition::InsideH) .size(5) .color("FF0000".to_owned()) ) ); } #[test] fn test_read_no_attr_vmerge() { let c = r#" "#; let mut parser = EventReader::new(c.as_bytes()); let cell = TableCell::read(&mut parser, &[]).unwrap(); assert_eq!( cell, TableCell::new() .add_paragraph(Paragraph::new().add_run(Run::new())) .width(6425, WidthType::DXA) .vertical_merge(VMergeType::Continue), ); } #[test] fn test_read_valign() { let c = r#" "#; let mut parser = EventReader::new(c.as_bytes()); let cell = TableCell::read(&mut parser, &[]).unwrap(); assert_eq!( cell, TableCell::new() .add_paragraph(Paragraph::new().add_run(Run::new())) .width(6425, WidthType::DXA) .vertical_align(VAlignType::Bottom), ); } }