xml: Support CDATA

This commit is contained in:
Lennart
2025-02-05 17:56:52 +01:00
parent 0596fe6396
commit 89f2483dac
4 changed files with 45 additions and 3 deletions

View File

@@ -111,7 +111,8 @@ impl NamedStruct {
if untagged_field_branches.len() > 1 { if untagged_field_branches.len() > 1 {
panic!("Currently only one untagged field supported!"); panic!("Currently only one untagged field supported!");
} }
let text_field_branches = self.fields.iter().filter_map(Field::text_branch); let text_field_branches: Vec<_> =
self.fields.iter().filter_map(Field::text_branch).collect();
let attr_field_branches = self.fields.iter().filter_map(Field::attr_branch); let attr_field_branches = self.fields.iter().filter_map(Field::attr_branch);
let tagname_field_branches = self.fields.iter().filter_map(Field::tagname_branch); let tagname_field_branches = self.fields.iter().filter_map(Field::tagname_branch);
@@ -175,7 +176,8 @@ impl NamedStruct {
#(#text_field_branches)* #(#text_field_branches)*
} }
Event::CData(cdata) => { Event::CData(cdata) => {
return Err(XmlError::UnsupportedEvent("CDATA")); let text = String::from_utf8(cdata.to_vec())?;
#(#text_field_branches)*
} }
Event::Comment(_) => { /* ignore */ } Event::Comment(_) => { /* ignore */ }
Event::Decl(_) => { Event::Decl(_) => {
@@ -191,7 +193,7 @@ impl NamedStruct {
return Err(XmlError::UnsupportedEvent("Doctype in the middle of the document")); return Err(XmlError::UnsupportedEvent("Doctype in the middle of the document"));
} }
Event::End(end) => { Event::End(end) => {
// Error: premature end // This should actually be unreachable
return Err(XmlError::Other("Unexpected closing tag for wrong element".to_owned())); return Err(XmlError::Other("Unexpected closing tag for wrong element".to_owned()));
} }
} }

View File

@@ -1,3 +1,5 @@
use std::string::FromUtf8Error;
use thiserror::Error; use thiserror::Error;
#[derive(Debug, Error)] #[derive(Debug, Error)]
@@ -6,6 +8,8 @@ pub enum XmlError {
QuickXmlError(#[from] quick_xml::Error), QuickXmlError(#[from] quick_xml::Error),
#[error(transparent)] #[error(transparent)]
QuickXmlAttrError(#[from] quick_xml::events::attributes::AttrError), QuickXmlAttrError(#[from] quick_xml::events::attributes::AttrError),
#[error(transparent)]
FromUtf8Error(#[from] FromUtf8Error),
#[error("Invalid tag [{0}]{1}. Expected [{2}]{3}")] #[error("Invalid tag [{0}]{1}. Expected [{2}]{3}")]
InvalidTag(String, String, String, String), InvalidTag(String, String, String, String),
#[error("Missing field {0}")] #[error("Missing field {0}")]

View File

@@ -81,6 +81,14 @@ impl<T: ValueDeserialize> XmlDeserialize for T {
} }
string = String::from_utf8_lossy(text.as_ref()).to_string(); string = String::from_utf8_lossy(text.as_ref()).to_string();
} }
Event::CData(cdata) => {
let text = String::from_utf8(cdata.to_vec())?;
if !string.is_empty() {
// Content already written
return Err(XmlError::UnsupportedEvent("content already written"));
}
string = text;
}
Event::End(_) => break, Event::End(_) => break,
Event::Eof => return Err(XmlError::Eof), Event::Eof => return Err(XmlError::Eof),
_ => return Err(XmlError::UnsupportedEvent("todo")), _ => return Err(XmlError::UnsupportedEvent("todo")),

View File

@@ -257,6 +257,34 @@ fn test_xml_values() {
); );
} }
#[test]
fn test_xml_cdata() {
#[derive(XmlDeserialize, XmlRootTag, PartialEq, Debug)]
#[xml(root = b"document")]
struct Document {
#[xml(ty = "text")]
hello: String,
href: String,
}
let doc = Document::parse_str(
r#"
<document>
<![CDATA[some text]]>
<href><![CDATA[some stuff]]></href>
</document>
"#,
)
.unwrap();
assert_eq!(
doc,
Document {
hello: "some text".to_owned(),
href: "some stuff".to_owned()
}
);
}
#[test] #[test]
fn test_struct_xml_decl() { fn test_struct_xml_decl() {
#[derive(Debug, XmlDeserialize, XmlRootTag, PartialEq)] #[derive(Debug, XmlDeserialize, XmlRootTag, PartialEq)]