重构Golang XML解析结构体
重构Golang XML解析结构体 我有一个如下所示的结构体
// ReportsImport 原始数据源,用于报告列表。仅使用 SysrptID、Name、FileName。
// 这很混乱,但拆分它似乎会影响反序列化
type ReportsImport struct {
XMLName xml.Name `xml:"ReportsImport"`
//Text string `xml:",chardata"`
//Xsi string `xml:"xsi,attr"`
//Xsd string `xml:"xsd,attr"`
Reports struct {
// Text string `xml:",chardata"`
ReportImport []struct {
Text string `xml:",chardata"`
SysrptID string `xml:"sysrptID"`
SQLVersion string `xml:"sqlVersion"`
FileName string `xml:"FileName"`
Name string `xml:"Name"`
ReportImport []struct {
Text string `xml:",chardata"`
SysrptID string `xml:"sysrptID"`
SQLVersion string `xml:"sqlVersion"`
FileName string `xml:"FileName"`
Name string `xml:"Name"`
ReportImport []struct {
Text string `xml:",chardata"`
SysrptID string `xml:"sysrptID"`
SQLVersion string `xml:"sqlVersion"`
FileName string `xml:"FileName"`
Name string `xml:"Name"`
} `xml:"ReportImport"`
} `xml:"ReportImport"`
} `xml:"ReportImport"`
} `xml:"Reports"`
//Path string `xml:"Path"`
}
用于解析如下所示的 XML 文件
<?xml version="1.0" encoding="utf-8"?>
<ReportsImport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Reports>
<ReportImport>
<sysrptID>1</sysrptID>
<sqlVersion>8</sqlVersion>
<FileName>MDR\Account Statistics.RPT</FileName>
<Name>MDR - Account Statistics</Name>
</ReportImport>
<ReportImport>
<sysrptID>2</sysrptID>
<sqlVersion>8</sqlVersion>
<FileName>CTE\Call Progress.RPT</FileName>
<Name>CTE - Call Progress</Name>
</ReportImport>
<ReportImport>
<sysrptID>295</sysrptID>
<sqlVersion>9</sqlVersion>
<FileName>IS\Genesis Account Statistics minutes.rpt</FileName>
<Name>Genesis - Account Statistics Minutes</Name>
</ReportImport>
</Reports>
<Path>E:\Reports\Version20\</Path>
</ReportsImport>
它能够工作,但我想清理这个结构体并将其拆分为一个列表和单个项目,类似于这样
type Import struct {
XMLName xml.Name `xml:"ReportsImport"`
Reports []ReportImport `xml:"Reports"`
}
type ReportImport struct {
XMLName xml.Name `xml:"ReportImport"`
Text string `xml:",chardata"`
SysrptID string `xml:"sysrptID"`
SQLVersion string `xml:"sqlVersion"`
FileName string `xml:"FileName"`
Name string `xml:"Name"`
}
但是当我这样做时,集合是 nil 或长度为零,不确定我遗漏了什么。
这个 XML 有点奇怪,但它是一个旧项目[为其生成的],我无法控制。
更多关于重构Golang XML解析结构体的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于重构Golang XML解析结构体的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
根据你的XML结构,问题在于XML中的Reports元素包含的是ReportImport子元素,但你的结构体定义中Reports字段的类型是[]ReportImport,而实际上它应该是一个包含ReportImport切片的结构体。
以下是正确的重构方案:
package main
import (
"encoding/xml"
"fmt"
)
type Import struct {
XMLName xml.Name `xml:"ReportsImport"`
Reports Reports `xml:"Reports"`
}
type Reports struct {
ReportImport []ReportImport `xml:"ReportImport"`
}
type ReportImport struct {
SysrptID string `xml:"sysrptID"`
SQLVersion string `xml:"sqlVersion"`
FileName string `xml:"FileName"`
Name string `xml:"Name"`
}
func main() {
xmlData := `<?xml version="1.0" encoding="utf-8"?>
<ReportsImport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Reports>
<ReportImport>
<sysrptID>1</sysrptID>
<sqlVersion>8</sqlVersion>
<FileName>MDR\Account Statistics.RPT</FileName>
<Name>MDR - Account Statistics</Name>
</ReportImport>
<ReportImport>
<sysrptID>2</sysrptID>
<sqlVersion>8</sqlVersion>
<FileName>CTE\Call Progress.RPT</FileName>
<Name>CTE - Call Progress</Name>
</ReportImport>
<ReportImport>
<sysrptID>295</sysrptID>
<sqlVersion>9</sqlVersion>
<FileName>IS\Genesis Account Statistics minutes.rpt</FileName>
<Name>Genesis - Account Statistics Minutes</Name>
</ReportImport>
</Reports>
<Path>E:\Reports\Version20\</Path>
</ReportsImport>`
var data Import
err := xml.Unmarshal([]byte(xmlData), &data)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Total reports: %d\n", len(data.Reports.ReportImport))
for i, report := range data.Reports.ReportImport {
fmt.Printf("Report %d: ID=%s, Name=%s\n", i+1, report.SysrptID, report.Name)
}
}
如果你想要更简洁的结构,也可以使用嵌套切片:
type Import struct {
XMLName xml.Name `xml:"ReportsImport"`
Reports []ReportImport `xml:"Reports>ReportImport"`
}
type ReportImport struct {
SysrptID string `xml:"sysrptID"`
SQLVersion string `xml:"sqlVersion"`
FileName string `xml:"FileName"`
Name string `xml:"Name"`
}
func main() {
xmlData := `<?xml version="1.0" encoding="utf-8"?>
<ReportsImport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Reports>
<ReportImport>
<sysrptID>1</sysrptID>
<sqlVersion>8</sqlVersion>
<FileName>MDR\Account Statistics.RPT</FileName>
<Name>MDR - Account Statistics</Name>
</ReportImport>
</Reports>
</ReportsImport>`
var data Import
err := xml.Unmarshal([]byte(xmlData), &data)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Total reports: %d\n", len(data.Reports))
}
两种方案都能正确解析你的XML数据。第一种方案更符合XML的层次结构,第二种方案使用xml:"Reports>ReportImport"标签来直接映射嵌套元素。

