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

Go语言中如何反序列化含两种嵌套内容的XML标签?

解决XML标签混合类型数据的解析问题(根据属性值适配不同字段类型)

问题背景

需要解析一种XML数据,其中<custom-attribute>标签的内容类型由attribute-id属性决定:有的标签直接包含字符数据,有的则包含嵌套的<value>子标签。现有代码只能处理单一类型,需实现根据属性值支持不同字段类型的解析逻辑。

解决方案

通过为CustomAttribute结构体实现xml.Unmarshaler接口,自定义XML解析逻辑,根据attribute-id的值选择解析字符数据还是嵌套的<value>子元素。

修改后的完整代码

package main

import (
    "encoding/xml"
    "fmt"
)

type CustomAttribute struct {
    AttributeID string   `xml:"attribute-id,attr"`
    StringValue string   // 存储字符数据类型的值
    SliceValue  []string // 存储嵌套<value>标签的内容
}

// 实现xml.Unmarshaler接口,自定义解析逻辑
func (ca *CustomAttribute) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    // 先解析attribute-id属性
    for _, attr := range start.Attr {
        if attr.Name.Local == "attribute-id" {
            ca.AttributeID = attr.Value
            break
        }
    }

    // 根据属性值分支处理解析逻辑
    switch ca.AttributeID {
    case "shipmentChangelog":
        // 解析嵌套的<value>标签集合
        var valuesWrapper struct {
            Values []string `xml:"value"`
        }
        if err := d.DecodeElement(&valuesWrapper, &start); err != nil {
            return err
        }
        ca.SliceValue = valuesWrapper.Values
    default:
        // 解析直接的字符数据内容
        var rawContent string
        if err := d.DecodeElement(&rawContent, &start); err != nil {
            return err
        }
        ca.StringValue = rawContent
    }
    return nil
}

type Customer struct {
    CustomAttributes []CustomAttribute `xml:"custom-attribute"`
}

func main() {
    xmlData := `
        <customer>
            <custom-attribute attribute-id="shipmentChangelog">
                <value>06/16/2023 9:22:49 AM PST Shipment has been cancelled: 60686167</value>
                <value>06/22/2023 2:19:10 PM PST Product has been removed: {"id":"47606963","pid":"FBS100402080001"}</value>
            </custom-attribute>
            <custom-attribute attribute-id="isCustomerImported">false</custom-attribute>
            <custom-attribute attribute-id="customerName">JohnDoe</custom-attribute>
        </customer>
    `

    var customer Customer
    if err := xml.Unmarshal([]byte(xmlData), &customer); err != nil {
        fmt.Println("Error:", err)
        return
    }

    // 打印解析结果
    for _, attr := range customer.CustomAttributes {
        fmt.Printf("Attribute ID: %s\n", attr.AttributeID)
        if attr.StringValue != "" {
            fmt.Printf("String Value: %s\n", attr.StringValue)
        }
        if len(attr.SliceValue) > 0 {
            fmt.Println("Slice Values:")
            for _, v := range attr.SliceValue {
                fmt.Printf("  - %s\n", v)
            }
        }
        fmt.Println("---")
    }
}

代码说明

  1. 结构体扩展:新增StringValue和SliceValue字段,分别对应两种不同类型的内容存储。
  2. 自定义解析逻辑:
    • 先提取attribute-id属性值,作为解析分支的判断依据;
    • 针对shipmentChangelog类型,解析嵌套的<value>标签到字符串切片;其他类型直接解析字符数据到字符串字段。
  3. 结果使用:解析完成后,可通过字段是否为空判断当前属性的内容类型,进而正确读取对应数据。

运行输出示例

Attribute ID: shipmentChangelog
Slice Values:
  - 06/16/2023 9:22:49 AM PST Shipment has been cancelled: 60686167
  - 06/22/2023 2:19:10 PM PST Product has been removed: {"id":"47606963","pid":"FBS100402080001"}
---
Attribute ID: isCustomerImported
String Value: false
---
Attribute ID: customerName
String Value: JohnDoe
---

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 21:30:15