use std::collections::HashMap;
use roxmltree::Node;
use super::ns_common::collect_ns_declarations;
use super::serialize::NsRenderer;
pub(crate) struct InclusiveNsRenderer;
impl NsRenderer for InclusiveNsRenderer {
fn render_namespaces<'a>(
&self,
node: Node<'a, '_>,
parent_rendered: &HashMap<String, String>,
) -> (Vec<(String, String)>, HashMap<String, String>) {
collect_ns_declarations(node, parent_rendered, |_, _| true)
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::super::serialize::{C14nConfig, serialize_canonical};
use super::*;
use roxmltree::Document;
#[test]
fn namespaces_rendered_on_first_element() {
let xml = r#"<root xmlns="http://example.com" xmlns:a="http://a.com"><child/></root>"#;
let doc = Document::parse(xml).expect("parse");
let renderer = InclusiveNsRenderer;
let mut out = Vec::new();
serialize_canonical(
&doc,
None,
false,
&renderer,
C14nConfig {
inherit_xml_attrs: true,
fixup_xml_base: false,
},
&mut out,
)
.expect("c14n");
let result = String::from_utf8(out).expect("utf8");
assert!(result.contains(r#"xmlns="http://example.com""#));
assert!(result.contains(r#"xmlns:a="http://a.com""#));
}
#[test]
fn inherited_ns_not_redeclared() {
let xml = r#"<root xmlns:a="http://a.com"><child xmlns:a="http://a.com"/></root>"#;
let doc = Document::parse(xml).expect("parse");
let renderer = InclusiveNsRenderer;
let mut out = Vec::new();
serialize_canonical(
&doc,
None,
false,
&renderer,
C14nConfig {
inherit_xml_attrs: true,
fixup_xml_base: false,
},
&mut out,
)
.expect("c14n");
let result = String::from_utf8(out).expect("utf8");
assert_eq!(
result,
r#"<root xmlns:a="http://a.com"><child></child></root>"#
);
}
#[test]
fn overridden_ns_is_redeclared() {
let xml = r#"<root xmlns:a="http://a.com"><child xmlns:a="http://other.com"/></root>"#;
let doc = Document::parse(xml).expect("parse");
let renderer = InclusiveNsRenderer;
let mut out = Vec::new();
serialize_canonical(
&doc,
None,
false,
&renderer,
C14nConfig {
inherit_xml_attrs: true,
fixup_xml_base: false,
},
&mut out,
)
.expect("c14n");
let result = String::from_utf8(out).expect("utf8");
assert!(result.contains(r#"<child xmlns:a="http://other.com">"#));
}
#[test]
fn default_ns_undeclared() {
let xml = r#"<root xmlns="http://example.com"><child xmlns=""/></root>"#;
let doc = Document::parse(xml).expect("parse");
let renderer = InclusiveNsRenderer;
let mut out = Vec::new();
serialize_canonical(
&doc,
None,
false,
&renderer,
C14nConfig {
inherit_xml_attrs: true,
fixup_xml_base: false,
},
&mut out,
)
.expect("c14n");
let result = String::from_utf8(out).expect("utf8");
assert!(result.contains(r#"<child xmlns="">"#));
}
#[test]
fn ns_decls_sorted_by_prefix() {
let xml =
r#"<root xmlns:z="http://z.com" xmlns:a="http://a.com" xmlns="http://default.com"/>"#;
let doc = Document::parse(xml).expect("parse");
let renderer = InclusiveNsRenderer;
let mut out = Vec::new();
serialize_canonical(
&doc,
None,
false,
&renderer,
C14nConfig {
inherit_xml_attrs: true,
fixup_xml_base: false,
},
&mut out,
)
.expect("c14n");
let result = String::from_utf8(out).expect("utf8");
let idx_default = result.find(r#"xmlns=""#).expect("default ns");
let idx_a = result.find(r#"xmlns:a="#).expect("a ns");
let idx_z = result.find(r#"xmlns:z="#).expect("z ns");
assert!(idx_default < idx_a, "default before a");
assert!(idx_a < idx_z, "a before z");
}
}