英文:
How to marshal xml with optional tags in Go
问题
我的问题是这样的:我需要将数据编组为SOAP XML。我目前得到的结果是:
<Carriage>
<mainCarriage loadFactor="70" seaCargoType="Container">
<sea xmlns="http://www.example.com/XMLSchema/standard/2012"></sea>
</mainCarriage>
</Carriage>
但我需要的结果是:
<Carriage>
<mainCarriage>
<sea xmlns="http://www.example.com/XMLSchema/standard/2012" loadFactor="70" seaCargoType="Container"></sea>
</mainCarriage>
</Carriage>
无论我尝试什么,我都无法将结构体编组为loadFactor和seaCargoType是sea标签的属性。
Carriage结构体采用空接口,因为根据货运类型,标签应该是sea或road,但不能同时存在。
英文:
The code for my problem is here: https://play.golang.org/p/X8Ey2hqmxL
package main
import (
"encoding/xml"
"fmt"
"log"
)
type Carriage struct {
MainCarriage interface{} `xml:"mainCarriage"`
}
type SeaCarriage struct {
Sea xml.Name `xml:"http://www.example.com/XMLSchema/standard/2012 sea"`
LoadFactor float64 `xml:"loadFactor,attr"`
SeaCargoType string `xml:"seaCargoType,attr"`
}
type RoadCarriage struct {
Road xml.Name `xml:"http://www.example.com/XMLSchema/standard/2012 road"`
}
func main() {
fr := Carriage{
MainCarriage: SeaCarriage{
LoadFactor: 70,
SeaCargoType: "Container",
},
}
xmlBlob, err := xml.MarshalIndent(&fr, "", "\t")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(xmlBlob))
}
I need to marshall data into SOAP xml. I'm currently getting this result:
<Carriage>
<mainCarriage loadFactor="70" seaCargoType="Container">
<sea xmlns="http://www.example.com/XMLSchema/standard/2012"></sea>
</mainCarriage>
</Carriage>
But I need this result:
<Carriage>
<mainCarriage>
<sea xmlns="http://www.example.com/XMLSchema/standard/2012" loadFactor="70" seaCargoType="Container"></sea>
</mainCarriage>
</Carriage>
No matter what I try I cannot marshal the structs so that the loadFactor and the seaCargoType are attrs of the sea tag.
The Carriage struct takes an empty interface because depending on the shipment type the tag should be either sea or road but never both.
答案1
得分: 2
在mainCarriage字段标签后面加上>.,表示你想将字段的内容放在mainCarriage标签内。根据编组器的要求,将Sea字段的名称更改为XMLName。
package main
import (
"encoding/xml"
"fmt"
"log"
)
type Carriage struct {
MainCarriage interface{} `xml:"mainCarriage>."`
}
type SeaCarriage struct {
XMLName xml.Name `xml:"http://www.example.com/XMLSchema/standard/2012 sea"`
LoadFactor float64 `xml:"loadFactor,attr"`
SeaCargoType string `xml:"seaCargoType,attr"`
}
type RoadCarriage struct {
Road xml.Name `xml:"http://www.example.com/XMLSchema/standard/2012 road"`
}
func main() {
fr := Carriage{
MainCarriage: SeaCarriage{
LoadFactor: 70,
SeaCargoType: "Container",
},
}
xmlBlob, err := xml.MarshalIndent(&fr, "", "\t")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(xmlBlob))
}
<kbd>Playground</kbd>
英文:
Put >. after mainCarriage field tag to indicate that you want to put contents of the field inside mainCarriage tag. Change the name of Sea field to XMLName as required by marshaller.
package main
import (
"encoding/xml"
"fmt"
"log"
)
type Carriage struct {
MainCarriage interface{} `xml:"mainCarriage>."`
}
type SeaCarriage struct {
XMLName xml.Name `xml:"http://www.example.com/XMLSchema/standard/2012 sea"`
LoadFactor float64 `xml:"loadFactor,attr"`
SeaCargoType string `xml:"seaCargoType,attr"`
}
type RoadCarriage struct {
Road xml.Name `xml:"http://www.example.com/XMLSchema/standard/2012 road"`
}
func main() {
fr := Carriage{
MainCarriage: SeaCarriage{
LoadFactor: 70,
SeaCargoType: "Container",
},
}
xmlBlob, err := xml.MarshalIndent(&fr, "", "\t")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(xmlBlob))
}
<kbd>Playground</kbd>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论