minidom: Allow passing prefixes alongside a reader

Maxime “pep” Buquet created

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

Change summary

minidom/src/element.rs      | 31 +++++++++++++++++++++++++++++++
minidom/src/tree_builder.rs |  9 +++++++++
2 files changed, 40 insertions(+)

Detailed changes

minidom/src/element.rs 🔗

@@ -346,6 +346,25 @@ impl Element {
         Err(Error::EndOfDocument)
     }
 
+    /// Parse a document from a `BufRead`, allowing Prefixes to be specified. Useful to provide
+    /// knowledge of namespaces that would have been declared on parent elements not present in the
+    /// reader.
+    pub fn from_reader_with_prefixes<R: BufRead, P: Into<Prefixes>>(
+        reader: R,
+        prefixes: P,
+    ) -> Result<Element> {
+        let mut tree_builder = TreeBuilder::new().with_prefixes_stack(vec![prefixes.into()]);
+        let mut driver = PullDriver::wrap(reader, Lexer::new(), RawParser::new());
+        while let Some(event) = driver.read()? {
+            tree_builder.process_event(event)?;
+
+            if let Some(root) = tree_builder.root.take() {
+                return Ok(root);
+            }
+        }
+        Err(Error::EndOfDocument)
+    }
+
     /// Output a document to a `Writer`.
     pub fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
         self.to_writer(&mut ItemWriter::new(writer))
@@ -958,4 +977,16 @@ mod tests {
         assert_eq!(elem, elem3);
         assert_eq!(elem, elem4);
     }
+
+    #[test]
+    fn test_from_reader_with_prefixes() {
+        let xml = b"<foo><bar xmlns='baz'/></foo>";
+        let elem =
+            Element::from_reader_with_prefixes(&xml[..], String::from("jabber:client")).unwrap();
+
+        let xml2 = b"<foo xmlns='jabber:client'><bar xmlns='baz'/></foo>";
+        let elem2 = Element::from_reader(&xml2[..]).unwrap();
+
+        assert_eq!(elem, elem2);
+    }
 }

minidom/src/tree_builder.rs 🔗

@@ -29,6 +29,15 @@ impl TreeBuilder {
         }
     }
 
+    /// Allow setting prefixes stack.
+    ///
+    /// Useful to provide knowledge of namespaces that would have been declared on parent elements
+    /// not present in the reader.
+    pub fn with_prefixes_stack(mut self, prefixes_stack: Vec<Prefixes>) -> Self {
+        self.prefixes_stack = prefixes_stack;
+        self
+    }
+
     /// Stack depth
     pub fn depth(&self) -> usize {
         self.stack.len()