使用Go语言解析嵌套的XML数据结构

huangapple go评论75阅读模式
英文:

Unmarshal Nested xml with Go

问题

我有以下一段代码片段,我一直在努力让它正常工作,但一直没有成功。我已经在各个地方搜索解决方案,但我找到的解决方案似乎都不起作用。

似乎我在xml.Unmarshal命令的映射方面存在问题,特别是涉及嵌套字段的部分。下面的代码可以成功获取顶层的unit值。

另外两个字段的值都为零,它们是嵌套两层的。这意味着结构设置不正确。以下是代码:

package main

import (
	"encoding/xml"
	"fmt"
)

type datevalue struct {
	Date  int     `xml:"date"`
	Value float32 `xml:"value"`
}

type pv struct {
	XMLName    xml.Name   `xml:"series"`
	Unit       string     `xml:"unit"`
	datevalues datevalue  `xml:"values>dateValue"`
}

func main() {
	contents := `<series>
                       <timeUnit>DAY</timeUnit>
                       <unit>Wh</unit><measuredBy>INVERTER</measuredBy>
                       <values><dateValue>
                            <date>2015-11-04 00:00:00</date>
                            <value>5935.405</value>
                       </dateValue></values>
                    </series>`

	m := &pv{}
	xml.Unmarshal([]byte(contents), &m)
	fmt.Printf("%s %f %d\n", m.Unit, m.datevalues.Value, m.datevalues.Date)
}

以下是输出结果:

Wh 0.000000 0
英文:

I have the following snippet of code that I have been banging my head on the wall trying to make it work. I have searched everywhere for a solution, but none of the ones that I have found seem to work.

It seems that I have an issue with my mapping for the xml.Unmarshal command as it pertains to nested fields. The code below works for retrieving the first value which is called unit, and is on the top level of the xml code.

The other two fields come up as zero, and they are nested two level deep. That implies that the structure isn't set up correctly. Here is the code.

package main

import (
	&quot;encoding/xml&quot;
	&quot;fmt&quot;
)

type datevalue struct {
	Date  int     `xml:&quot;date&quot;`
	Value float32 `xml:&quot;value&quot;`
}

type pv struct {
	XMLName    xml.Name  `xml:&quot;series&quot;`
	Unit       string    `xml:&quot;unit&quot;`
	datevalues datevalue `xml:&quot;values&gt;dateValue&quot;`
}

func main() {
	contents := `&lt;series&gt;
                   &lt;timeUnit&gt;DAY&lt;/timeUnit&gt;
                   &lt;unit&gt;Wh&lt;/unit&gt;&lt;measuredBy&gt;INVERTER&lt;/measuredBy&gt;
                   &lt;values&gt;&lt;dateValue&gt;
                        &lt;date&gt;2015-11-04 00:00:00&lt;/date&gt;
                        &lt;value&gt;5935.405&lt;/value&gt;
                   &lt;/dateValue&gt;&lt;/values&gt;
                &lt;/series&gt;`

	m := &amp;pv{}
	xml.Unmarshal([]byte(contents), &amp;m)
	fmt.Printf(&quot;%s %f %d\n&quot;, m.Unit, m.datevalues.Value, m.datevalues.Date)
}

And here is the output:

Wh 0.000000 0

答案1

得分: 12

首先,你的代码不起作用,因为你应该使用导出的字段进行编组/解组(参见https://golang.org/pkg/encoding/xml/)。
你应该使用

type pv struct {
    XMLName    xml.Name  `xml:"series"`
    Unit       string    `xml:"unit"`
    Datevalues datevalue `xml:"values>dateValue"`
}

而不是

type pv struct {
    XMLName    xml.Name  `xml:"series"`
    Unit       string    `xml:"unit"`
    datevalues datevalue `xml:"values>dateValue"`
}

注意DateValues字段的名称。如果第一个字符大写,它将被导出。否则,在Unmarshal时将忽略该字段。

其次:

之后,我注意到你忽略了错误。请不要忽略它们,它们非常有用。

kbd上检查一下。

如你所见,你在datatypeDate字段中使用了int数据类型。如果你将类型更改为string,你的代码将起作用。

第三:

我认为你真正想将你的date值解组为time.Time
你可以参考这个相关的问题

你可以在kbd上尝试完整的可工作代码。

英文:

First of all your code doesn't work because you should use exported fields for marshalling/unmarshalling (see https://golang.org/pkg/encoding/xml/).
You should use

type pv struct {
	XMLName    xml.Name  `xml:&quot;series&quot;`
	Unit       string    `xml:&quot;unit&quot;`
	Datevalues datevalue `xml:&quot;values&gt;dateValue&quot;`
}

instead of

type pv struct {
	XMLName    xml.Name  `xml:&quot;series&quot;`
	Unit       string    `xml:&quot;unit&quot;`
	datevalues datevalue `xml:&quot;values&gt;dateValue&quot;`
}

Look at DateValues field name. If first symbol is uppercased it's will be exported. Otherwise that field will be ignored while Unmarshal

Second:

After it I noticed that you are ignoring your errors. Please don't ignore them, they are critically useful.

Check it out on the <kbd>go playgroung</kbd>

As you can see you use int datatype for Date field of datatype.
If you change type to string, your code will work.

Third:

I think you really want to unmarshall your date value into time.Time.
To do so you can check this related question

The complete working code you can try on the <kbd>go playground</kbd>

huangapple
  • 本文由 发表于 2015年11月6日 08:30:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/33557401.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定