xml - xml 编组和解组 xsi:type
问题描述
这是关于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>
如您所见,添加了属性xmlns:xsi="xsi"这不是我想要的
解决此问题的方法是使用自定义解组器,但这似乎不必要地复杂和冗长。(下面的代码)。有没有更简单的方法来做到这一点?处理这种 XML 的常规方法是什么?
解决方法代码(在操场上: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))
}
解决方案
从技术上讲,示例中的黄金结果(我的意思是第一个)似乎不是格式良好的 XML。它具有属性的未绑定 xml 元素前缀xsi
。xsi:type
我认为,这个规范为此设定了权威规则。这个 XML 片段看起来没有竞争力,如果它是更大文档的一部分,那么xsi
前缀可能会绑定到其他地方——这对于 SOAP 文档很常见。
请注意,Go Marshaller 生成格式良好的 XML。由于片段中缺少 DTD 等原因,该文档仍然不是有效的 XML,但它至少不会混淆任何 XML 解析器。
作为一个更广泛的建议,匹配用于测试或任何东西的 XML 文档的确切文本表示最有可能产生较差的结果,因为在 XML 中编码文档的语法正确(且格式正确)的方法不止一种。不同的编组器可以根据作者的喜好调整特定的编码方法,这不会使生成的 XML 损坏或与任何其他兼容的解码器不兼容。尝试比较未编组的结构,而不是比较文本片段。像github.com/google/go-cmp/cmp包这样的东西可以让它变得简单。
推荐阅读
- azure-web-app-service - 如何通过 Azure App Service 上发布的 Blazor Webassembly 中的自定义 URL 使用 OIDC
- node.js - 无法在浏览器应用程序选项卡中使用 NodeJs 设置 Cookie,即使它响应
- c# - 如何在 C# 中复制对象?
- node.js - 如何为 Web 应用程序配置 cgi-express?
- macos - Jenkins 管道失败并出现错误:“docker : permission deinied”
- java - Spring - 将请求 Content-Type: text/plain 更改为 Content-Type: multipart/form-data in a Filter
- ios - 为什么在 ios 上输入 react Crossed?
- python - 如何在 Django 中添加并通过电子邮件发送与会者邀请(Google 日历集成)
- r - 透视/组合 R 中的表以根据键 ID 列获取行(tidyverse?)
- yaml - PanDoc - 如何使用 pandoc_title_block 扩展在 docx 的标题中插入变量?