XML-атрибут Golang и значение
Я не могу понять, почему это не работает.
type HostProperties struct {
XMLName xml.Name `xml:HostProperties"`
Info []InfoList `xml:"tag"`
}
type InfoList struct {
HostEnd string `xml:",chardata"`
PatchSummary string `xml:",chardata"`
CPE1 string `xml:",chardata"`
CPE0 string `xml:",chardata"`
SystemType string `xml:",chardata"`
OperatingSystem string `xml:",chardata"`
MacAddress string `xml:",chardata"`
Traceroute string `xml:",chardata"`
IP string `xml:",chardata"`
FQDN string `xml:",chardata"`
HostStart string `xml:",chardata"`
}
<HostProperties>
<tag name="HOST_END">Thu Feb 20 12:38:24 2014</tag>
<tag name="patch-summary-total-cves">4</tag>
<tag name="cpe-1">cpe:/a:openbsd:openssh:5.6 -> OpenBSD OpenSSH 5.6</tag>
<tag name="cpe-0">cpe:/o:vmware:esx_server</tag>
<tag name="system-type">hypervisor</tag>
<tag name="operating-system">VMware ESXi</tag>
<tag name="mac-address">00:00:00:00:00:00</tag>
<tag name="traceroute-hop-0">172.28.28.29</tag>
<tag name="host-ip">172.28.28.29</tag>
<tag name="host-fqdn">foobar.com</tag>
<tag name="HOST_START">Thu Feb 20 12:30:14 2014</tag>
</HostProperties>
Результаты
{HostEnd:172.28.28.29 PatchSummary: CPE1: CPE0: SystemType: OperatingSystem: MacAddress: Traceroute: IP: FQDN: HostStart:}
Он создает кучу новых срезов с заполненным только первым элементом и даже тогда неправильным элементом. Он не заполняет другие переменные. Остальная часть файла, похоже, отлично разбирается, просто не может понять эту часть.
Ответы
Ответ 1
Я не думаю, что вы можете заставить XML-парсинг работать так. Вот лучшее, что я мог придумать (запустить его на игровой площадке)
var data = `<HostProperties>
<tag name="HOST_END">Thu Feb 20 12:38:24 2014</tag>
<tag name="patch-summary-total-cves">4</tag>
<tag name="cpe-1">cpe:/a:openbsd:openssh:5.6 -> OpenBSD OpenSSH 5.6</tag>
<tag name="cpe-0">cpe:/o:vmware:esx_server</tag>
<tag name="system-type">hypervisor</tag>
<tag name="operating-system">VMware ESXi</tag>
<tag name="mac-address">00:00:00:00:00:00</tag>
<tag name="traceroute-hop-0">172.28.28.29</tag>
<tag name="host-ip">172.28.28.29</tag>
<tag name="host-fqdn">foobar.com</tag>
<tag name="HOST_START">Thu Feb 20 12:30:14 2014</tag>
</HostProperties>`
type HostProperties struct {
XMLName xml.Name `xml:HostProperties"`
Tags []Tag `xml:"tag"`
}
type Tag struct {
Key string `xml:"name,attr"`
Value string `xml:",chardata"`
}
func main() {
v := new(HostProperties)
err := xml.Unmarshal([]byte(data), v)
if err != nil {
fmt.Printf("error: %v", err)
return
}
fmt.Printf("v = %#v\n", v)
}
Если вам действительно нужна структура InfoList
, вам нужно будет запустить через Tags
и заполнить ее. Я бы, вероятно, просто вставлял ее в map[string]string
, хотя вроде бы
tags := make(map[string]string)
for _, tag := range v.Tags {
tags[tag.Key] = tag.Value
}
fmt.Printf("map = %#v\n", tags)
Ответ 2
Тег xml:",chardata"
будет выбирать текущие символьные данные элемента, как вы хотите, но только для первого поля с этим тегом. Вот почему вы получили результаты, которые вы наблюдали.
Для данного XML я предлагаю декодировать следующие типы:
type HostProperties struct {
XMLName xml.Name `xml:"HostProperties"`
Info []Tag `xml:"tag"`
}
type Tag struct {
Name string `xml:"name,attr"`
Value string `xml:",chardata"`
}
Он не будет автоматически разделять различные именованные теги на отдельные поля для вас: вам нужно будет сделать это после обработки XML.