这与xsi:type属性有关,但是如果您有一个名为<< [[soap:envelope ...>的元素,则在似乎有必要实现自定义拆组器功能时也会出现类似问题。
这里是有问题的代码(在旅途中:https://play.golang.org/p/ORQsINYS-9o)type PayloadPublication struct {
XMLName xml.Name `json:"xmlName"`
XsiType xml.Attr `xml:"xsi type,attr" json:"xsiType"`
Lang xml.Attr `xml:"lang,attr" json:"lang"`
}
func main() {
payload := PayloadPublication{}
expectedXML := `<payloadPublication xmlns="http://datex2.eu/schema/2/2_0" xsi:type="MeasurementSiteTablePublication" lang="nl"></payloadPublication>`
// 1. Unmarshal - 2. Marshal - 3. Compare
err := xml.Unmarshal([]byte(expectedXML), &payload)
if err != nil {
fmt.Print(err.Error())
}
result, err := xml.Marshal(payload)
if err != nil {
fmt.Print(err.Error())
}
fmt.Printf("expected: %v\n", expectedXML)
fmt.Printf("result: %v\n", string(result))
}
结果
expected: <payloadPublication xmlns="http://datex2.eu/schema/2/2_0" xsi:type="MeasurementSiteTablePublication" lang="nl"></payloadPublication> result: <payloadPublication xmlns="http://datex2.eu/schema/2/2_0" xmlns:xsi="xsi" xsi:type="MeasurementSiteTablePublication" lang="nl"></payloadPublication>
如您所见,添加了属性,这不是我想要的一种解决方法是使用自定义拆组器,但这似乎是不必要的复杂和冗长。 (下面的代码)。有没有更简单的方法可以做到这一点?处理这种XML的常规方法是什么?xmlns:xsi =“ xsi”
解决方法代码(在操场上:https://play.golang.org/p/d4OtYPtYBDg)
type PayloadPublication struct {
XMLName xml.Name `json:"xmlName"`
XsiType xml.Attr `xml:"xsi type,attr" json:"xsiType"`
Lang xml.Attr `xml:"lang,attr" json:"lang"`
}
func (pp *PayloadPublication) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// Attributes
for _, attr := range start.Attr {
if attr.Name.Local == "type" {
pp.XsiType = xml.Attr{Name: xml.Name{Local: "xsi:type"}, Value: attr.Value}
}
}
var dummy struct {
// attributes
XMLName xml.Name `json:"xmlName"`
XsiType xml.Attr `xml:"xsi type,attr" json:"xsiType"`
Lang xml.Attr `xml:"lang,attr" json:"lang"`
}
err := d.DecodeElement(&dummy, &start)
if err != nil {
return err
}
pp.XMLName = dummy.XMLName
pp.Lang = dummy.Lang
return nil
}
func main() {
payload := PayloadPublication{}
expectedXML := `<payloadPublication xmlns="http://datex2.eu/schema/2/2_0" xsi:type="MeasurementSiteTablePublication" lang="nl"></payloadPublication>`
// 1. Unmarshal - 2. Marshal - 3. Compare
err := xml.Unmarshal([]byte(expectedXML), &payload)
if err != nil {
fmt.Print(err.Error())
}
result, err := xml.Marshal(payload)
if err != nil {
fmt.Print(err.Error())
}
fmt.Printf("expected: %v\n", expectedXML)
fmt.Printf("result: %v\n", string(result))
}
xsi
属性的未绑定xml元素前缀xsi:type
。我认为,this spec为此设置了权威规则。该XML代码段似乎是不争的事实,如果它是较大文档的一部分,则xsi
前缀可能会绑定到其他位置-对于SOAP文档来说,这很常见。请注意,Go Marshaller会生成格式正确的XML。由于片段中缺少DTD等原因,该文档仍然不是有效的XML,但至少它不会混淆任何XML解析器。
作为更广泛的建议,匹配XML文档的精确文本表示形式以进行测试或其他任何操作都可能产生较差的结果,因为存在多种语法上正确(且格式正确)的XML编码文档的方法。不同的编组人员可以根据作者的喜好来调整特定的编码方法,这不会使生成的XML损坏或与任何其他兼容的解码器不兼容。与其比较文本片段,不如尝试比较未编组的结构。 github.com/google/go-cmp/cmp封装之类的东西可以使其变得简单。