minidom: Include prefixes in serialization when using `Element::from_reader_with_prefixes`

Maxime “pep” Buquet created

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>

Change summary

minidom/CHANGELOG.md        |  2 ++
minidom/src/element.rs      | 16 ++++++++++++++++
minidom/src/tree_builder.rs | 10 +++++++++-
3 files changed, 27 insertions(+), 1 deletion(-)

Detailed changes

minidom/CHANGELOG.md 🔗

@@ -4,6 +4,8 @@ Version NEXT:
     * Update rxml dependency to 0.13.
   * Fixes
     * Remove warnings for elided lifetimes (rustc 1.90)
+    * Fixes serialization and ensure prefixes are set on Element when using
+      `Element::from_reader_with_prefixes`.
 
 Version 0.16, released 2024-07-23:
   * Breaking

minidom/src/element.rs 🔗

@@ -1077,6 +1077,22 @@ mod tests {
         assert_eq!(elem, elem2);
     }
 
+    #[test]
+    fn test_from_reader_with_prefixes_serialization() {
+        let prefixes: BTreeMap<Option<String>, String> = {
+            let mut tmp = BTreeMap::new();
+            tmp.insert(None, String::from("foo"));
+            tmp.insert(Some(String::from("test")), String::from("bar"));
+            tmp
+        };
+
+        let input = r#"<foo test:attr="true"><bar/></foo>"#;
+        let output = r#"<foo xmlns='foo' xmlns:test='bar' test:attr='true'><bar/></foo>"#;
+
+        let elem = Element::from_reader_with_prefixes(input.as_ref(), prefixes).unwrap();
+        assert_eq!(String::from(&elem), output);
+    }
+
     #[test]
     fn failure_with_duplicate_namespace() {
         let _: Element = r###"<?xml version="1.0" encoding="UTF-8"?>

minidom/src/tree_builder.rs 🔗

@@ -113,10 +113,18 @@ impl TreeBuilder {
             RawEvent::XmlDeclaration(_, _) => {}
 
             RawEvent::ElementHeadOpen(_, (prefix, name)) => {
+                // If self.prefixes_stack has been set via with_prefixes_stack before processing,
+                // ensure these are set on the root element.
+                let prefixes = if self.stack.is_empty() && self.prefixes_stack.len() == 1 {
+                    self.prefixes_stack.pop().unwrap()
+                } else {
+                    Prefixes::default()
+                };
+
                 self.next_tag = Some((
                     prefix.map(|prefix| prefix.as_str().to_owned()),
                     name.as_str().to_owned(),
-                    Prefixes::default(),
+                    prefixes,
                     BTreeMap::new(),
                 ));
             }