use crate::io::XmlNamespace;
pub(crate) fn try_strip_leading_slash(target: &str) -> &str {
match target.strip_prefix('/') {
Some(stripped) => stripped,
None => target,
}
}
pub fn parse_xmlns_attributes(tag_content: &str) -> Vec<XmlNamespace> {
let mut attributes = Vec::new();
let mut chars = tag_content.chars().peekable();
while let Some(ch) = chars.next() {
if ch == 'x' {
let mut attr_name = String::from("x");
let mut is_xmlns = true;
for expected in ['m', 'l', 'n', 's'] {
if chars.peek() == Some(&expected) {
attr_name.push(chars.next().unwrap());
} else {
is_xmlns = false;
break;
}
}
if is_xmlns {
let prefix = if chars.peek() == Some(&':') {
chars.next(); let mut prefix_str = String::new();
while let Some(&ch) = chars.peek() {
if ch.is_alphabetic() || ch == '_' || ch == '-' {
prefix_str.push(chars.next().unwrap());
} else {
break;
}
}
Some(prefix_str)
} else {
None
};
if chars.next() == Some('=') && chars.next() == Some('"') {
let mut uri = String::new();
for ch in chars.by_ref() {
if ch == '"' {
break;
}
uri.push(ch);
}
attributes.push(XmlNamespace { prefix, uri });
}
}
}
}
attributes
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_xmlns_attributes_simple() {
let xml = r#"<model xmlns="http://schemas.microsoft.com/3dmanufacturing/core/2015/02" unit="millimeter">"#;
let attrs = parse_xmlns_attributes(xml);
assert_eq!(
attrs,
vec![XmlNamespace {
prefix: None,
uri: "http://schemas.microsoft.com/3dmanufacturing/core/2015/02".to_string()
}]
);
}
#[test]
fn test_parse_xmlns_attributes_prefixed() {
let xml = r#"<model xmlns="http://core" xmlns:p="http://prod" xmlns:b="http://beam">"#;
let attrs = parse_xmlns_attributes(xml);
assert_eq!(
attrs,
vec![
XmlNamespace {
prefix: None,
uri: "http://core".to_string()
},
XmlNamespace {
prefix: Some("p".to_string()),
uri: "http://prod".to_string()
},
XmlNamespace {
prefix: Some("b".to_string()),
uri: "http://beam".to_string()
},
]
);
}
#[test]
fn test_parse_xmlns_attributes_empty() {
let xml = r#"<model unit="millimeter">"#;
let attrs = parse_xmlns_attributes(xml);
assert_eq!(attrs, Vec::<XmlNamespace>::new());
}
#[test]
fn test_parse_xmlns_attributes_mixed() {
let xml = r#"<model xmlns="http://core" unit="millimeter" xmlns:p="http://prod" requiredextensions="ext">"#;
let attrs = parse_xmlns_attributes(xml);
assert_eq!(
attrs,
vec![
XmlNamespace {
prefix: None,
uri: "http://core".to_string()
},
XmlNamespace {
prefix: Some("p".to_string()),
uri: "http://prod".to_string()
},
]
);
}
}