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

如何将XML反序列化为Go语言的空接口或map[string]any?

Go中XML反序列化为any或map[string]any的实现方法

标准库encoding/xml本身不支持直接将XML反序列化为any或map[string]any——这是因为XML的树形结构(包含标签名、属性、文本内容等)比JSON的键值对结构更复杂,标准库无法自动推断映射规则。但可以通过自定义递归结构体的方式实现类似效果,把XML解析为层级化的map结构。

实现方案:自定义递归节点结构体

定义一个包含XML标签名、属性、文本内容和子节点的结构体,利用xml:",any"标签捕获所有未知子元素,再将结构体递归转换为map[string]any。

package main

import (
	"encoding/xml"
	"fmt"
)

// Node 通用XML节点结构,用于捕获所有元素、属性和文本
type Node struct {
	XMLName xml.Name
	Attrs   []xml.Attr `xml:"-"` // 捕获所有属性
	Content string     `xml:",chardata"` // 捕获节点文本内容
	Nodes   []Node     `xml:",any"` // 捕获所有子节点
}

// ToMap 将Node转换为map[string]any结构
func (n Node) ToMap() any {
	// 如果是纯文本节点,直接返回文本内容
	if len(n.Nodes) == 0 && n.Content != "" {
		return n.Content
	}

	m := make(map[string]any)

	// 处理属性,存入@attrs字段
	if len(n.Attrs) > 0 {
		attrs := make(map[string]string)
		for _, attr := range n.Attrs {
			attrs[attr.Name.Local] = attr.Value
		}
		m["@attrs"] = attrs
	}

	// 处理子节点,按标签名分组
	childMap := make(map[string][]any)
	for _, node := range n.Nodes {
		childMap[node.XMLName.Local] = append(childMap[node.XMLName.Local], node.ToMap())
	}

	// 子节点如果只有一个,直接存单个值;多个则存数组
	for tag, children := range childMap {
		if len(children) == 1 {
			m[tag] = children[0]
		} else {
			m[tag] = children
		}
	}

	return m
}

func main() {
	rawXML := []byte(`
	<regionalRating>
		<rating>TV-PG</rating>
		<region>CA</region>
	</regionalRating>
	`)

	var root Node
	if err := xml.Unmarshal(rawXML, &root); err != nil {
		panic(err)
	}

	// 转换为map[string]any并打印
	result := root.ToMap().(map[string]any)
	fmt.Printf("%#v\n", result)
	// 输出:map[string]any{"rating":"TV-PG", "region":"CA"}
}

补充说明

  • 上述实现会保留XML的属性(存入@attrs字段)、文本内容和层级结构,同时自动处理单个/多个同名子节点的情况。
  • 如果不需要保留XML属性或特殊结构,也可以先将XML转换为JSON(自定义简单转换逻辑),再反序列化为map[string]any,但这种方式会丢失XML特有的信息,仅适合简单场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:47:19