quick-xml icon indicating copy to clipboard operation
quick-xml copied to clipboard

text data in tag contents

Open eirnym opened this issue 6 months ago • 3 comments

I have a data file which I cannot (shouldn't ask to) change:

<?xml version="1.0" encoding="utf-8"?>
<root>
	<key>
		<value id="1">text1</value>
		<value id="2">text2</value>
		<value id="3">text3</value>
		<value id="4">text4</value>d
		<value id="5">text5</value>
		<value id="6">text6</value>
	<key>
</root>

When I deserialize using quick-xml & serde, I have an error, with this d, which I'd love to ignore completely

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename = "root")]
pub struct Root {
  #[serde(rename = "key")]
  pub key: Key,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename = "key")]
pub struct Key {
  #[serde(rename = "value")]
  pub values: Option<Vec<Value>>
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename = "Value")]
pub struct Value {
  #[serde(rename = "@id")]
  pub id: String

  #[serde(rename = "$text")]
  pub text: Option<String>
}

Error I have and I'd like to ignore is Error: invalid type: string "d", expected struct Value

eirnym avatar Jun 14 '25 14:06 eirnym

You could introduce intermediate type to accept text and ignore it. Something like

fn deserialize_values<'de, D>(deserializer: D) -> Result<Option<Vec<Value>>, D::Error>
where D: Deserializer<'de>,
{
  #[derive(Deserialize)]
  enum Workaround {
    #[serde(rename = "value")]
    Value(Value),
    #[serde(rename = "$text")]
    Text,
  }
  let data: Option<Vec<Workaround>> = Deserialize::deserialize(deserializer)?;
  // convert to Option<Vec<Value>> by skipping Workaround::Text elements
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename = "key")]
pub struct Key {
  #[serde(rename = "$value", deserialize_with = "deserialize_values")]
  pub values: Option<Vec<Value>>,
}

Note, that values should be renamed to $value so we can catch text data, and not only <value> tags

Mingun avatar Jun 14 '25 16:06 Mingun

this is a possibility, thank you, I do this way in another problematic XML node, but there was a Choice enum from the beginning

I wonder why I have to specify this in quick-xml, while I can ignore it in serde_json. Maybe you can give some light on the difference.

eirnym avatar Jun 14 '25 18:06 eirnym

This is a bug. It should skip texts when deserialize sequences of elements with fixed name. The fix is coming

Mingun avatar Jun 14 '25 21:06 Mingun