You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用quick-xml反序列化EVTX XML至Rust对象时遇UnexpectedStart错误

问题解决:quick-xml解析EVTX XML时的UnexpectedStart错误

错误原因

报错failed to ds the xml: UnexpectedStart([77, 101, 115, 115, 97, 103, 101])中的字节数组对应字符串Message,核心问题有三点:

  1. RenderingInfo结构体定义错误:你用#[serde(rename = "$value")]尝试将<RenderingInfo>下的所有内容解析为message文本,但该标签下除了<Message>还有<Level>、<Task>等多个子元素,解析器遇到这些额外的起始标签时抛出错误。
  2. 字段命名与serde配置不匹配:结构体字段使用大写开头(如EventID),不符合Rust蛇形命名规范,且与rename_all = "PascalCase"的自动映射逻辑冲突,会导致字段无法正确匹配XML标签。
  3. 未处理XML命名空间:<Event>标签带有xmlns属性,quick-xml默认会严格匹配命名空间,未指定时无法正确识别根元素。

修复方案及修改后代码

修正后的结构体定义

use serde::Deserialize;

#[derive(Debug, Deserialize)]
#[serde(rename = "Event", namespace = "http://schemas.microsoft.com/win/2004/08/events/event")]
#[serde(rename_all = "PascalCase")]
pub struct Event {
    system: System,
    event_data: EventData,
    rendering_info: RenderingInfo,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct System {
    // 若需要Provider可取消注释并定义对应结构体
    // provider: Provider,
    event_id: String,
    version: String,
    level: String,
    task: String,
    opcode: String,
    keywords: String,
    time_created: TimeCreated,
    event_record_id: String,
    channel: String,
    computer: String,
    security: String,
    // 忽略System下不需要的Correlation、Execution等元素
    #[serde(flatten)]
    _ignored: std::collections::HashMap<String, serde_json::Value>,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct TimeCreated {
    #[serde(rename = "@SystemTime")]
    system_time: String,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct EventData {
    data: Vec<Data>,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct Data {
    #[serde(rename = "$value")]
    value: String,
    #[serde(rename = "@Name")]
    name: String,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct RenderingInfo {
    #[serde(rename = "@Culture")]
    culture: String,
    message: String,
    // 忽略RenderingInfo下不需要的Level、Task等元素
    #[serde(flatten)]
    _ignored: std::collections::HashMap<String, serde_json::Value>,
}

修正后的main.rs代码

use std::path::PathBuf;
use evtx::EvtxParser;
use quick_xml::de::from_str;

fn main() {
    let fp = PathBuf::from("/Users/arshiamohammadi/Documents/rust/evtx_parser/records/logs1.evtx");

    let mut parser = EvtxParser::from_path(fp).unwrap();
    for record in parser.records() {
        match record {
            Ok(r) => {
                let event: Event = from_str(&r.data).expect("failed to deserialize the xml");
                println!("{:#?}", event);
            },
            Err(e) => eprintln!("{}", e),
        }
        break;
    }
}

关键修改说明

  1. 修复RenderingInfo解析逻辑:移除$value注解,直接定义message字段匹配XML中的<Message>标签,用#[serde(flatten)]捕获并忽略不需要的子元素,避免解析时遇到未定义标签报错。
  2. 规范字段命名:将所有结构体字段改为Rust标准的蛇形命名(如event_id代替EventID),配合rename_all = "PascalCase"自动映射XML的PascalCase标签,既符合规范又保证映射正确。
  3. 处理XML命名空间:在Event结构体上添加命名空间注解,明确指定EVTX XML的官方命名空间,让quick-xml能够正确识别根元素。
  4. 忽略多余元素:在System和RenderingInfo中添加_ignored字段,用于捕获XML中存在但不需要解析的子元素,避免解析失败。

内容的提问来源于stack exchange,提问作者arshia mohammadi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 02:07:32