diff --git a/core/src/avm1/globals/xml.rs b/core/src/avm1/globals/xml.rs
index 5ba75f4e8..9350f7fba 100644
--- a/core/src/avm1/globals/xml.rs
+++ b/core/src/avm1/globals/xml.rs
@@ -199,7 +199,7 @@ pub fn xmlnode_to_string<'gc>(
if let Some(node) = this.as_xml_node() {
let mut writer = Writer::new(Cursor::new(&mut result));
- node.write_node_to_event_writer(&mut writer);
+ node.write_node_to_event_writer(&mut writer, &mut is_as2_compatible);
}
Ok(String::from_utf8(result)
@@ -669,7 +669,7 @@ pub fn create_xml_proto<'gc>(
if let Some(doctype) = node.document().doctype() {
let mut result = Vec::new();
let mut writer = Writer::new(Cursor::new(&mut result));
- if let Err(e) = doctype.write_node_to_event_writer(&mut writer) {
+ if let Err(e) = doctype.write_node_to_event_writer(&mut writer, &mut |_| true) {
log::warn!("Error occured when serializing DOCTYPE: {}", e);
}
diff --git a/core/src/xml/tests.rs b/core/src/xml/tests.rs
index 32a6b251d..f29f0f555 100644
--- a/core/src/xml/tests.rs
+++ b/core/src/xml/tests.rs
@@ -2,7 +2,9 @@
use crate::xml;
use crate::xml::{XMLDocument, XMLName};
+use quick_xml::Writer;
use gc_arena::rootless_arena;
+use std::io::Cursor;
/// Tests very basic parsing of a single-element document.
#[test]
@@ -70,3 +72,43 @@ fn double_ended_children() {
assert!(roots.next_back().is_none());
})
}
+
+/// Tests round-trip XML writing behavior.
+#[test]
+fn round_trip_tostring() {
+ let test_string = "This is a text node";
+
+ rootless_arena(|mc| {
+ let xml = XMLDocument::new(mc);
+ xml.as_node()
+ .replace_with_str(mc, test_string)
+ .expect("Parsed document");
+
+ let mut buf = Vec::new();
+ let mut writer = Writer::new(Cursor::new(&mut buf));
+ xml.as_node().write_node_to_event_writer(&mut writer, &mut |_| true).expect("Successful toString");
+ let result = String::from_utf8(buf).expect("Valid UTF-8");
+
+ assert_eq!(test_string, result);
+ })
+}
+
+/// Tests filtered XML writing behavior.
+#[test]
+fn round_trip_filtered_tostring() {
+ let test_string = "This is a text node";
+
+ rootless_arena(|mc| {
+ let xml = XMLDocument::new(mc);
+ xml.as_node()
+ .replace_with_str(mc, test_string)
+ .expect("Parsed document");
+
+ let mut buf = Vec::new();
+ let mut writer = Writer::new(Cursor::new(&mut buf));
+ xml.as_node().write_node_to_event_writer(&mut writer, &mut |node| !node.is_comment()).expect("Successful toString");
+ let result = String::from_utf8(buf).expect("Valid UTF-8");
+
+ assert_eq!("This is a text node", result);
+ })
+}
\ No newline at end of file
diff --git a/core/src/xml/tree.rs b/core/src/xml/tree.rs
index c38f95c83..ac8e61180 100644
--- a/core/src/xml/tree.rs
+++ b/core/src/xml/tree.rs
@@ -983,6 +983,15 @@ impl<'gc> XMLNode<'gc> {
}
}
+ /// Check if this XML node constitutes text.
+ #[allow(dead_code)]
+ pub fn is_comment(self) -> bool {
+ match &*self.0.read() {
+ XMLNodeData::Comment { .. } => true,
+ _ => false,
+ }
+ }
+
/// Check if this XML node constitutes a DOCTYPE declaration
pub fn is_doctype(self) -> bool {
match &*self.0.read() {
@@ -1168,11 +1177,28 @@ impl<'gc> XMLNode<'gc> {
}
}
- pub fn write_node_to_event_writer(self, writer: &mut Writer) -> Result<(), Error>
+ /// Write the contents of this node, including it's children, to the given
+ /// writer.
+ ///
+ /// The given filter function allows filtering specific children out of the
+ /// resulting write stream. It will be called at least once for each node
+ /// encountered in the tree (other than this one) if specified; only nodes
+ /// that yield `true` shall be printed.
+ pub fn write_node_to_event_writer(self, writer: &mut Writer, filter: &mut F) -> Result<(), Error>
where
W: Write,
+ F: FnMut(XMLNode<'gc>) -> bool
{
- let children_len = self.children_len();
+ let mut children = Vec::new();
+ if let Some(my_children) = self.children() {
+ for child in my_children {
+ if filter(child) {
+ children.push(child)
+ }
+ }
+ }
+
+ let children_len = children.len();
match &*self.0.read() {
XMLNodeData::DocumentRoot { .. } => Ok(0),
@@ -1213,11 +1239,9 @@ impl<'gc> XMLNode<'gc> {
BytesText::from_plain_str(contents.as_str()),
)),
}?;
-
- if let Some(children) = self.children() {
- for child in children {
- child.write_node_to_event_writer(writer)?;
- }
+
+ for child in children {
+ child.write_node_to_event_writer(writer, filter)?;
}
match &*self.0.read() {