用多种可能的类型解析XML标记[Rust, serde, serde- XML -rs]



我想解析一个可能包含不同数据类型的XML元素。

下面是我能想到的最简单的例子:

use serde_derive::{Deserialize, Serialize};
use serde_xml_rs::{from_str};
const XML: &str = r#"
<element>
foo
</element>
"#;
const XML2: &str = r#"
<element>
123
</element>
"#;
#[derive(Serialize, Deserialize, Debug, PartialEq)]
enum Element {
#[serde(rename="element")]
Text(String),
#[serde(rename="element")]
Number(i32),
}
fn main() {
let el: Element = from_str(&XML).unwrap();
println!("{:?}", &el);
println!("nnnn");
let el2: Element = from_str(&XML2).unwrap();
println!("{:?}", &el2);
}

当前代码解析元素文本(字符串),而不是文本(字符串)、数量(手机等)分别。

如果我颠倒顺序,程序会崩溃,因为"foo"不能解析为整数。

#[derive(Serialize, Deserialize, Debug, PartialEq)]
enum Element {
#[serde(rename="element")]
Number(i32),
#[serde(rename="element")]
Text(String),
}

如何正确实现程序?

如果我正确理解你的帖子,你想要Number,只要值可以解析为i32Text,否则。您可以使用FromStr特性来实现它。

#[derive(Serialize, serde_with::DeserializeFromStr, Debug, PartialEq)]
enum Element {
#[serde(rename="element")]
Text(String),
#[serde(rename="element")]
Number(i32),
}
impl std::str::FromStr for Element {
type Err = std::convert::Infallible;

fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(i) = s.parse::<i32>() {
Ok(Element::Number(i))
} else {
Ok(Element::Text(s.to_string()))
}
}
}