#![allow(dead_code)]
use crate::error::PptxError;
pub const NSMAP: &[(&str, &str)] = &[
("a", NS_A),
("c", NS_C),
("cp", NS_CP),
("ct", NS_CT),
("dc", NS_DC),
("dcmitype", NS_DCMITYPE),
("dcterms", NS_DCTERMS),
("ep", NS_EP),
("i", NS_I),
("m", NS_M),
("mo", NS_MO),
("mv", NS_MV),
("o", NS_O),
("p", NS_P),
("pd", NS_PD),
("pic", NS_PIC),
("pr", NS_PR),
("r", NS_R),
("sl", NS_SL),
("v", NS_V),
("ve", NS_VE),
("w", NS_W),
("w10", NS_W10),
("wne", NS_WNE),
("wp", NS_WP),
("xsi", NS_XSI),
("p14", NS_P14),
("dgm", NS_DGM),
("mc", NS_MC),
];
pub const NS_A: &str = "http://schemas.openxmlformats.org/drawingml/2006/main";
pub const NS_C: &str = "http://schemas.openxmlformats.org/drawingml/2006/chart";
pub const NS_CP: &str = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
pub const NS_CT: &str = "http://schemas.openxmlformats.org/package/2006/content-types";
pub const NS_DC: &str = "http://purl.org/dc/elements/1.1/";
pub const NS_DCMITYPE: &str = "http://purl.org/dc/dcmitype/";
pub const NS_DCTERMS: &str = "http://purl.org/dc/terms/";
pub const NS_EP: &str = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
pub const NS_I: &str = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
pub const NS_M: &str = "http://schemas.openxmlformats.org/officeDocument/2006/math";
pub const NS_MO: &str = "http://schemas.microsoft.com/office/mac/office/2008/main";
pub const NS_MV: &str = "urn:schemas-microsoft-com:mac:vml";
pub const NS_O: &str = "urn:schemas-microsoft-com:office:office";
pub const NS_P: &str = "http://schemas.openxmlformats.org/presentationml/2006/main";
pub const NS_PD: &str = "http://schemas.openxmlformats.org/drawingml/2006/presentationDrawing";
pub const NS_PIC: &str = "http://schemas.openxmlformats.org/drawingml/2006/picture";
pub const NS_PR: &str = "http://schemas.openxmlformats.org/package/2006/relationships";
pub const NS_R: &str = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
pub const NS_SL: &str =
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout";
pub const NS_V: &str = "urn:schemas-microsoft-com:vml";
pub const NS_VE: &str = "http://schemas.openxmlformats.org/markup-compatibility/2006";
pub const NS_W: &str = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
pub const NS_W10: &str = "urn:schemas-microsoft-com:office:word";
pub const NS_WNE: &str = "http://schemas.microsoft.com/office/word/2006/wordml";
pub const NS_WP: &str = "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing";
pub const NS_XSI: &str = "http://www.w3.org/2001/XMLSchema-instance";
pub const NS_P14: &str = "http://schemas.microsoft.com/office/powerpoint/2010/main";
pub const NS_DGM: &str = "http://schemas.openxmlformats.org/drawingml/2006/diagram";
pub const NS_MC: &str = "http://schemas.openxmlformats.org/markup-compatibility/2006";
pub fn nsuri(prefix: &str) -> Result<&'static str, PptxError> {
NSMAP
.iter()
.find(|(pfx, _)| *pfx == prefix)
.map(|(_, uri)| *uri)
.ok_or_else(|| PptxError::InvalidXml(format!("unknown namespace prefix: {prefix:?}")))
}
pub fn prefix_for(uri: &str) -> Option<&'static str> {
NSMAP.iter().find(|(_, ns)| *ns == uri).map(|(pfx, _)| *pfx)
}
pub fn qn(tag: &str) -> Result<String, PptxError> {
let (prefix, local) = tag.split_once(':').ok_or_else(|| {
PptxError::InvalidXml(format!("tag must contain a ':' delimiter: {tag:?}"))
})?;
let uri = nsuri(prefix)?;
Ok(format!("{{{uri}}}{local}"))
}
pub fn nsdecls(prefixes: &[&str]) -> Result<String, PptxError> {
let mut parts = Vec::with_capacity(prefixes.len());
for pfx in prefixes {
let uri = nsuri(pfx)?;
parts.push(format!("xmlns:{pfx}=\"{uri}\""));
}
Ok(parts.join(" "))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_qn_resolves_prefixed_tag() {
assert_eq!(
qn("p:cSld").unwrap(),
"{http://schemas.openxmlformats.org/presentationml/2006/main}cSld"
);
assert_eq!(
qn("a:t").unwrap(),
"{http://schemas.openxmlformats.org/drawingml/2006/main}t"
);
assert_eq!(
qn("r:id").unwrap(),
"{http://schemas.openxmlformats.org/officeDocument/2006/relationships}id"
);
}
#[test]
fn test_nsuri_known_prefix() {
assert_eq!(
nsuri("p").unwrap(),
"http://schemas.openxmlformats.org/presentationml/2006/main"
);
}
#[test]
fn test_nsuri_unknown_prefix() {
let err = nsuri("unknown").unwrap_err();
assert!(err.to_string().contains("unknown namespace prefix"));
}
#[test]
fn test_prefix_for_known_uri() {
assert_eq!(
prefix_for("http://schemas.openxmlformats.org/drawingml/2006/main"),
Some("a")
);
}
#[test]
fn test_prefix_for_unknown_uri() {
assert_eq!(prefix_for("http://unknown"), None);
}
#[test]
fn test_nsdecls() {
let result = nsdecls(&["a", "r"]).unwrap();
assert!(result.contains("xmlns:a="));
assert!(result.contains("xmlns:r="));
}
#[test]
fn test_qn_error_on_missing_colon() {
let err = qn("noprefix").unwrap_err();
assert!(err.to_string().contains("tag must contain a ':' delimiter"));
}
#[test]
fn test_qn_error_on_unknown_prefix() {
let err = qn("zzz:tag").unwrap_err();
assert!(err.to_string().contains("unknown namespace prefix"));
}
#[test]
fn test_nsdecls_error_on_unknown_prefix() {
let err = nsdecls(&["a", "zzz"]).unwrap_err();
assert!(err.to_string().contains("unknown namespace prefix"));
}
}