Golang如何将动态XML数据解析到结构体
Golang如何将动态XML数据解析到结构体 你好,
我有一个XML数据,其中包含一些具有动态元素名称的重复数据,如下所示。
<Ht>
<Criteria>
<ADNode_1>2</ADNode_1>
<CDNode_1>2</CDNode_1>
<IFNode_1>0</IFNode_1>
<ADNode_2>2</ADNode_2>
<CDNode_2>0</CDNode_2>
<IFNode_2>0</IFNode_2>
<ADNode_3>0</ADNode_3>
<CDNode_3>0</CDNode_3>
<IFNode_3>0</IFNode_3>
</Criteria>
<session id="1056134770841202228344907">
<Htd ID="21170">
<Data_1>
<Info Count="2"></Info>
<Data Id="iV29308/B2/R1">
<Type>TR1</Type>
</Data>
<Data Id="iV29308/B3/R1">
<Type>TR1</Type>
</Data>
<Data Id="iV29308/B4/R1">
<Type>TR1</Type>
</Data>
<Data Id="iV29308/B6/R1">
<Type>TR1</Type>
</Data>
</Data_1>
<Data_2>
<Info Count="2"></Info>
<Data Id="iV29308/B2/R1">
<Type>TR2</Type>
</Data>
<Data Id="iV29308/B3/R1">
<Type>TR2</Type>
</Data>
<Data Id="iV29308/B4/R1">
<Type>TR2</Type>
</Data>
<Data Id="iV29308/B6/R1">
<Type>TR3</Type>
</Data>
</Data_2>
</Htd>
</session>
</Ht>
我可以为 <ADNode_1>、<ADNode_2> 和 <ADNode_3> 或 <Data_1>、<Data_2> 创建单独的结构体,但这些节点的数量可以是 n 个。
如下所示
<ADNode_1>2</ADNode_1>
<ADNode_2>2</ADNode_2>
<ADNode_3>2</ADNode_3>
.
.
<ADNode_n>2</ADNode_n>
或者
<Data_1></Data_1>
<Data_2></Data_2>
<Data_3></Data_3>
.
.
.
<Data_n></Data_n>
我应该如何创建这些节点的结构体,以容纳 n 个节点或元素?
这是 playground 链接。
更多关于Golang如何将动态XML数据解析到结构体的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang如何将动态XML数据解析到结构体的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
对于动态XML元素名称,可以使用xml.Unmarshal配合自定义的UnmarshalXML方法。以下是处理动态节点名称的示例:
package main
import (
"encoding/xml"
"fmt"
"strconv"
)
type Ht struct {
XMLName xml.Name `xml:"Ht"`
Criteria Criteria `xml:"Criteria"`
Session Session `xml:"session"`
}
type Criteria struct {
XMLName xml.Name `xml:"Criteria"`
Nodes []Node `xml:",any"`
}
type Node struct {
XMLName xml.Name
Value int `xml:",chardata"`
}
func (n *Node) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
n.XMLName = start.Name
var content string
if err := d.DecodeElement(&content, &start); err != nil {
return err
}
val, err := strconv.Atoi(content)
if err != nil {
return err
}
n.Value = val
return nil
}
type Session struct {
XMLName xml.Name `xml:"session"`
ID string `xml:"id,attr"`
Htd Htd `xml:"Htd"`
}
type Htd struct {
XMLName xml.Name `xml:"Htd"`
ID string `xml:"ID,attr"`
Data []Data `xml:",any"`
}
type Data struct {
XMLName xml.Name `xml:",any"`
Info Info `xml:"Info"`
Items []Item `xml:"Data"`
}
type Info struct {
XMLName xml.Name `xml:"Info"`
Count int `xml:"Count,attr"`
}
type Item struct {
XMLName xml.Name `xml:"Data"`
ID string `xml:"Id,attr"`
Type string `xml:"Type"`
}
func main() {
xmlData := `<Ht>
<Criteria>
<ADNode_1>2</ADNode_1>
<CDNode_1>2</CDNode_1>
<IFNode_1>0</IFNode_1>
<ADNode_2>2</ADNode_2>
<CDNode_2>0</CDNode_2>
<IFNode_2>0</IFNode_2>
<ADNode_3>0</ADNode_3>
<CDNode_3>0</CDNode_3>
<IFNode_3>0</IFNode_3>
</Criteria>
<session id="1056134770841202228344907">
<Htd ID="21170">
<Data_1>
<Info Count="2"></Info>
<Data Id="iV29308/B2/R1">
<Type>TR1</Type>
</Data>
<Data Id="iV29308/B3/R1">
<Type>TR1</Type>
</Data>
<Data Id="iV29308/B4/R1">
<Type>TR1</Type>
</Data>
<Data Id="iV29308/B6/R1">
<Type>TR1</Type>
</Data>
</Data_1>
<Data_2>
<Info Count="2"></Info>
<Data Id="iV29308/B2/R1">
<Type>TR2</Type>
</Data>
<Data Id="iV29308/B3/R1">
<Type>TR2</Type>
</Data>
<Data Id="iV29308/B4/R1">
<Type>TR2</Type>
</Data>
<Data Id="iV29308/B6/R1">
<Type>TR3</Type>
</Data>
</Data_2>
</Htd>
</session>
</Ht>`
var ht Ht
err := xml.Unmarshal([]byte(xmlData), &ht)
if err != nil {
panic(err)
}
fmt.Printf("Criteria节点数量: %d\n", len(ht.Criteria.Nodes))
for _, node := range ht.Criteria.Nodes {
fmt.Printf("节点名: %s, 值: %d\n", node.XMLName.Local, node.Value)
}
fmt.Printf("\nData节点数量: %d\n", len(ht.Session.Htd.Data))
for _, data := range ht.Session.Htd.Data {
fmt.Printf("Data节点名: %s, Info.Count: %d\n", data.XMLName.Local, data.Info.Count)
for _, item := range data.Items {
fmt.Printf(" Item ID: %s, Type: %s\n", item.ID, item.Type)
}
}
}
对于更复杂的动态XML处理,可以使用xml.Decoder进行流式解析:
package main
import (
"encoding/xml"
"fmt"
"io"
"strings"
)
func parseDynamicXML(xmlStr string) {
decoder := xml.NewDecoder(strings.NewReader(xmlStr))
for {
token, err := decoder.Token()
if err == io.EOF {
break
}
if err != nil {
panic(err)
}
switch se := token.(type) {
case xml.StartElement:
if se.Name.Local == "Criteria" {
parseCriteria(decoder)
} else if se.Name.Local == "Htd" {
parseHtd(decoder)
}
}
}
}
func parseCriteria(decoder *xml.Decoder) {
for {
token, err := decoder.Token()
if err != nil {
break
}
switch se := token.(type) {
case xml.StartElement:
if strings.HasPrefix(se.Name.Local, "ADNode_") ||
strings.HasPrefix(se.Name.Local, "CDNode_") ||
strings.HasPrefix(se.Name.Local, "IFNode_") {
var value string
decoder.DecodeElement(&value, &se)
fmt.Printf("动态节点: %s = %s\n", se.Name.Local, value)
}
case xml.EndElement:
if se.Name.Local == "Criteria" {
return
}
}
}
}
func parseHtd(decoder *xml.Decoder) {
for {
token, err := decoder.Token()
if err != nil {
break
}
switch se := token.(type) {
case xml.StartElement:
if strings.HasPrefix(se.Name.Local, "Data_") {
parseDataSection(decoder, se.Name.Local)
}
case xml.EndElement:
if se.Name.Local == "Htd" {
return
}
}
}
}
func parseDataSection(decoder *xml.Decoder, sectionName string) {
fmt.Printf("处理数据段: %s\n", sectionName)
for {
token, err := decoder.Token()
if err != nil {
break
}
switch se := token.(type) {
case xml.StartElement:
if se.Name.Local == "Info" {
var info struct {
Count int `xml:"Count,attr"`
}
decoder.DecodeElement(&info, &se)
fmt.Printf(" Info.Count: %d\n", info.Count)
} else if se.Name.Local == "Data" {
var data struct {
ID string `xml:"Id,attr"`
Type string `xml:"Type"`
}
decoder.DecodeElement(&data, &se)
fmt.Printf(" Data: ID=%s, Type=%s\n", data.ID, data.Type)
}
case xml.EndElement:
if se.Name.Local == sectionName {
return
}
}
}
}
func main() {
xmlData := `<Ht>
<Criteria>
<ADNode_1>2</ADNode_1>
<CDNode_1>2</CDNode_1>
<IFNode_1>0</IFNode_1>
</Criteria>
<session id="1056134770841202228344907">
<Htd ID="21170">
<Data_1>
<Info Count="2"></Info>
<Data Id="iV29308/B2/R1">
<Type>TR1</Type>
</Data>
</Data_1>
</Htd>
</session>
</Ht>`
parseDynamicXML(xmlData)
}
使用xml:",any"标签配合自定义的UnmarshalXML方法可以处理动态元素名称,而流式解析则提供了更大的灵活性来处理复杂的XML结构。

