XML 使用字段名称中的索引解组动态响应
XML unmarshal dynamic response with indices in field names
我正在尝试解组 "dynamic" XML 响应,但我不确定如何处理它。服务器响应相当大的响应,所以我不希望解析响应两次。 XML 看起来像这样:
...
<nic_cnt>2</nic_cnt>
<ifindex1>eno1</ifindex1>
<ifindex2>eno2</ifindex2>
...
因此 nic_cnt
字段定义了 ifindex
发生的次数。由于我不知道 ifindex
会发生多少次,因此我无法静态定义解组响应所需的结构字段。
您可以使用带有 ,any
XML 标签选项的切片来告诉 encoding/xml
package to put any XML tag into it. This is documented at xml.Unmarshal()
:
If the XML element contains a sub-element that hasn't matched any
of the above rules and the struct has a field with tag ",any",
unmarshal maps the sub-element to that struct field.
对于 <ifindexXX>
标签,使用另一个包含类型 xml.Name
的 XMLName
字段的结构,因此如果您只需要过滤以以下开头的字段,则实际的字段名称将可用ifindex
.
让我们解析以下XML:
<root>
<nic_cnt>2</nic_cnt>
<ifindex1>eno1</ifindex1>
<ifindex2>eno2</ifindex2>
</root>
我们可以用它建模:
type Root struct {
NicCnt int `xml:"nic_cnt"`
Entries []Entry `xml:",any"`
}
type Entry struct {
XMLName xml.Name
Value string `xml:",innerxml"`
}
解析它的示例代码:
var root Root
if err := xml.Unmarshal([]byte(src), &root); err != nil {
panic(err)
}
fmt.Printf("%+v", root)
输出(在 Go Playground 上尝试):
{NicCnt:2 Entries:[
{XMLName:{Space: Local:ifindex1} Value:eno1}
{XMLName:{Space: Local:ifindex2} Value:eno2}]}
请注意 Root.Entries
还将包含其他未映射的 XML 标签。如果您只关心以 ifindex
开头的标签,您可以这样 "filter" 它们:
for _, e := range root.Entries {
if strings.HasPrefix(e.XMLName.Local, "ifindex") {
fmt.Println(e.XMLName.Local, ":", e.Value)
}
}
如果XML还包含一个额外的标签:
<other>something else</other>
输出将是(在 Go Playground 上试试这个):
{NicCnt:2 Entries:[
{XMLName:{Space: Local:ifindex1} Value:eno1}
{XMLName:{Space: Local:ifindex2} Value:eno2}
{XMLName:{Space: Local:other} Value:something else}]}
ifindex1 : eno1
ifindex2 : eno2
我正在尝试解组 "dynamic" XML 响应,但我不确定如何处理它。服务器响应相当大的响应,所以我不希望解析响应两次。 XML 看起来像这样:
...
<nic_cnt>2</nic_cnt>
<ifindex1>eno1</ifindex1>
<ifindex2>eno2</ifindex2>
...
因此 nic_cnt
字段定义了 ifindex
发生的次数。由于我不知道 ifindex
会发生多少次,因此我无法静态定义解组响应所需的结构字段。
您可以使用带有 ,any
XML 标签选项的切片来告诉 encoding/xml
package to put any XML tag into it. This is documented at xml.Unmarshal()
:
If the XML element contains a sub-element that hasn't matched any of the above rules and the struct has a field with tag ",any", unmarshal maps the sub-element to that struct field.
对于 <ifindexXX>
标签,使用另一个包含类型 xml.Name
的 XMLName
字段的结构,因此如果您只需要过滤以以下开头的字段,则实际的字段名称将可用ifindex
.
让我们解析以下XML:
<root>
<nic_cnt>2</nic_cnt>
<ifindex1>eno1</ifindex1>
<ifindex2>eno2</ifindex2>
</root>
我们可以用它建模:
type Root struct {
NicCnt int `xml:"nic_cnt"`
Entries []Entry `xml:",any"`
}
type Entry struct {
XMLName xml.Name
Value string `xml:",innerxml"`
}
解析它的示例代码:
var root Root
if err := xml.Unmarshal([]byte(src), &root); err != nil {
panic(err)
}
fmt.Printf("%+v", root)
输出(在 Go Playground 上尝试):
{NicCnt:2 Entries:[
{XMLName:{Space: Local:ifindex1} Value:eno1}
{XMLName:{Space: Local:ifindex2} Value:eno2}]}
请注意 Root.Entries
还将包含其他未映射的 XML 标签。如果您只关心以 ifindex
开头的标签,您可以这样 "filter" 它们:
for _, e := range root.Entries {
if strings.HasPrefix(e.XMLName.Local, "ifindex") {
fmt.Println(e.XMLName.Local, ":", e.Value)
}
}
如果XML还包含一个额外的标签:
<other>something else</other>
输出将是(在 Go Playground 上试试这个):
{NicCnt:2 Entries:[
{XMLName:{Space: Local:ifindex1} Value:eno1}
{XMLName:{Space: Local:ifindex2} Value:eno2}
{XMLName:{Space: Local:other} Value:something else}]}
ifindex1 : eno1
ifindex2 : eno2