Repository: tafia/quick-xml
Pull request #603 (2023-05-24 17:56:24)

Trim next element after DocType
Allow comment to exist between DocType and root element

With the new EntityResolver/Doctype changes, putting an xml comment between a doctype and the root element causes the parse to fail. Trimming the next element fixes this.


Patch:
diff --git a/Changelog.md b/Changelog.md
index e0a0119..f1bf280 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -18,9 +18,15 @@
 
 ### Bug Fixes
 
+- [#603]: Fix a regression from [#581] that an XML comment or a processing
+  instruction between a <!DOCTYPE> and the root element in the file brokes
+  deserialization of structs by returning `DeError::ExpectedStart`
+
 ### Misc Changes
 
+[#581]: https://github.com/tafia/quick-xml/pull/581
 [#601]: https://github.com/tafia/quick-xml/pull/601
+[#603]: https://github.com/tafia/quick-xml/pull/603
 [#606]: https://github.com/tafia/quick-xml/pull/606
 
 
diff --git a/src/de/mod.rs b/src/de/mod.rs
index cc0d59d..20017d0 100644
--- a/src/de/mod.rs
+++ b/src/de/mod.rs
@@ -2880,7 +2880,7 @@ impl StartTrimmer {
     #[inline(always)]
     fn trim<'a>(&mut self, event: Event<'a>) -> Option<PayloadEvent<'a>> {
         let (event, trim_next_event) = match event {
-            Event::DocType(e) => (PayloadEvent::DocType(e), false),
+            Event::DocType(e) => (PayloadEvent::DocType(e), true),
             Event::Start(e) => (PayloadEvent::Start(e), true),
             Event::End(e) => (PayloadEvent::End(e), true),
             Event::Eof => (PayloadEvent::Eof, true),


Test patch:
diff --git a/tests/serde-de.rs b/tests/serde-de.rs
index 7b12fd0..554abac 100644
--- a/tests/serde-de.rs
+++ b/tests/serde-de.rs
@@ -6496,3 +6496,77 @@ mod resolve {
         );
     }
 }
+
+/// Tests for https://github.com/tafia/quick-xml/pull/603.
+///
+/// According to <https://www.w3.org/TR/xml11/#NT-prolog> comments,
+/// processing instructions and spaces are possible after XML declaration or DTD.
+/// Their existence should not break deserializing
+///
+/// ```text
+/// [22] prolog ::= XMLDecl Misc* (doctypedecl Misc*)?
+/// [27] Misc   ::= Comment | PI | S
+/// ```
+mod xml_prolog {
+    use super::*;
+    use pretty_assertions::assert_eq;
+    use std::collections::HashMap;
+
+    #[test]
+    fn spaces() {
+        assert_eq!(
+            from_str::<HashMap<(), ()>>(
+                r#"
+        <?xml version="1.1"?>
+
+        <!DOCTYPE dict>
+
+        <doc>
+        </doc>
+        "#
+            )
+            .unwrap(),
+            HashMap::new()
+        );
+    }
+
+    #[test]
+    fn comments() {
+        assert_eq!(
+            from_str::<HashMap<(), ()>>(
+                r#"
+        <?xml version="1.1"?>
+        <!-- comment between xml declaration and doctype -->
+        <!-- another comment -->
+        <!DOCTYPE dict>
+        <!-- comment between doctype and root element -->
+        <!-- another comment -->
+        <doc>
+        </doc>
+        "#,
+            )
+            .unwrap(),
+            HashMap::new()
+        );
+    }
+
+    #[test]
+    fn pi() {
+        assert_eq!(
+            from_str::<HashMap<(), ()>>(
+                r#"
+        <?xml version="1.1"?>
+        <?pi?>
+        <?another pi?>
+        <!DOCTYPE dict>
+        <?pi?>
+        <?another pi?>
+        <doc>
+        </doc>
+        "#,
+            )
+            .unwrap(),
+            HashMap::new()
+        );
+    }
+}