xlsbye_xml/
shared_strings.rs1use crate::writer::{Result, XmlWriter};
2use std::io::Write;
3use xlsbye_core::types::SharedStringTable;
4use xlsbye_core::xml_names::SPREADSHEET_NS;
5
6pub fn write_shared_strings(
7 writer: impl Write,
8 sst: &SharedStringTable,
9 count: u32,
10 unique_count: u32,
11) -> Result<()> {
12 let mut writer = XmlWriter::new(writer);
13 writer.write_xml_declaration()?;
14 writer.write_start_element_with_ns(
15 "sst",
16 [("", SPREADSHEET_NS)],
17 [
18 ("count", count.to_string()),
19 ("uniqueCount", unique_count.to_string()),
20 ],
21 )?;
22
23 for entry in sst {
24 writer.write_start_element("si", std::iter::empty::<(&str, &str)>())?;
25 match entry {
26 xlsbye_core::types::SharedStringEntry::Plain(text) => {
27 write_text_node(&mut writer, "t", text)?;
28 }
29 xlsbye_core::types::SharedStringEntry::Rich(runs) => {
30 for run in runs {
31 writer.write_start_element("r", std::iter::empty::<(&str, &str)>())?;
32 if let Some(font_index) = run.font_index {
33 writer.write_start_element("rPr", std::iter::empty::<(&str, &str)>())?;
34 writer.write_empty_element("rFont", [("val", format!("font{}", font_index))])?;
35 writer.write_end_element("rPr")?;
36 }
37 write_text_node(&mut writer, "t", &run.text)?;
38 writer.write_end_element("r")?;
39 }
40 }
41 }
42 writer.write_end_element("si")?;
43 }
44
45 writer.write_end_element("sst")?;
46 Ok(())
47}
48
49pub(crate) fn write_text_node<W: Write>(
50 writer: &mut XmlWriter<W>,
51 tag_name: &str,
52 text: &str,
53) -> Result<()> {
54 if needs_space_preserve(text) {
55 writer.write_text_element(tag_name, [("xml:space", "preserve")], text)
56 } else {
57 writer.write_text_element(tag_name, std::iter::empty::<(&str, &str)>(), text)
58 }
59}
60
61fn needs_space_preserve(text: &str) -> bool {
62 text.chars().next().is_some_and(char::is_whitespace)
63 || text.chars().last().is_some_and(char::is_whitespace)
64}