我有一个可以使用的XML结构
<Rights>
<Name>NAS</Name>
<Access>2</Access>
<Name>App</Name>
<Access>1</Access>
</Rights>
(显然)这是一个列表,可以保证它包含成对的Name, Access
(并且始终按该特定顺序)。我的问题:我可以使用encoding/xml
包的Unmarshal
函数在单个结构中解组Name
和Access
吗?
考虑以下示例:
package main
import (
"encoding/xml"
"fmt"
)
var XML = []string{`
?xml version="1.0" encoding="UTF-8"?>
<SessionInfo>
<SID>abc123</SID>
<Rights>
<Name>NAS</Name>
<Access>2</Access>
<Name>App</Name>
<Access>1</Access>
</Rights>
</SessionInfo>
`,`
<SessionInfo>
<SID>def456</SID>
<Rights />
</SessionInfo>
`}
type Right struct {
Name string
Access int
}
type SessionInfo struct {
XMLName xml.Name `xml:"SessionInfo"`
SID string
Rights []Right
}
func main() {
for _,entry := range XML {
info := SessionInfo{}
if err := xml.Unmarshal([]byte(entry), &info); err != nil {
fmt.Println("Marshal failed", err.Error())
continue
}
fmt.Printf("%+v\n", info)
}
}
此不按预期方式工作:
// Only the first value is found
{SID:abc123 Rights:[{Name:App Access:1}]}
// One (not existing) value was found and the struct's zero value was used
{SID:def456 Rights:[{Name: Access:0}]}
我可以(并且可以起作用)定义彼此独立的属性
Names []string `xml:"Rights>Name"`
Accesses []int `xml:"Rights>Access"`
但是我希望第一个版本的结构格式无需手动转换。
有没有办法获得预期的结果?
答案 0 :(得分:1)
我正在使用XPath
库xmlquery,而不是使用编组/解散方法。
package main
import (
"fmt"
"strings"
"github.com/antchfx/xmlquery"
)
func main() {
s := `
?xml version="1.0" encoding="UTF-8"?>
<SessionInfo>
<SID>abc123</SID>
<Rights>
<Name>NAS</Name>
<Access>2</Access>
<Name>App</Name>
<Access>1</Access>
</Rights>
</SessionInfo>
`
doc, err := xmlquery.Parse(strings.NewReader(s))
if err != nil {
panic(err)
}
for _, elem := range xmlquery.Find(doc, "//SessionInfo") {
sid := xmlquery.FindOne(elem, "SID")
fmt.Printf("sid: %s\n", sid.InnerText())
for _, name := range xmlquery.Find(elem, "Rights/Name") {
fmt.Printf("name: %s\n", name.InnerText())
}
}
}
输出
sid: abc123
name: NAS
name: App