英文:
How to getting an empty array when parsing XML?
问题
我被委托编写一个Go实用程序,它接受一个XML文件,解析它,并以JSON格式返回。
以下是XML的示例:
<?xml version="1.0" encoding="utf-8"?>
<tracks clid="020">
<track uuid="551" category="s" route="8" vehicle_type="trolleybus" >
<point
latitude="53.61491"
longitude="55.90922"
avg_speed="24"
direction="270"
time="13122022:072116"
/>
</track>
<track uuid="552" category="s" route="6" vehicle_type="trolleybus">
<point
latitude="53.68321"
longitude="57.90922"
avg_speed="42"
direction="181"
time="13122022:072216"
/>
</track>
</tracks>
我编写了以下代码:
package main
import (
"encoding/json"
"encoding/xml"
"fmt"
)
type Tracks struct {
XMLName xml.Name `xml:"tracks" json:"-"`
Clid string `xml:"clid,attr" json:"clid"`
Tracks []Track `xml:"track" json:"track_list"`
}
type Track struct {
XMLName xml.Name `xml:"tracks"`
Uuid string `xml:"uuid,attr" json:"uuid"`
Category string `xml:"category,attr" json:"category"`
Route string `xml:"route,attr" json:"route"`
VehicleType string `xml:"vehicle_type,attr" json:"vehicle_type"`
Point Point `xml:"point" json:"point"`
}
type Point struct {
Latitude string `xml:"latitude,attr" json:"latitude"`
Longitude string `xml:"longitude,attr" json:"longitude"`
AvgSpeed string `xml:"avg_speed,attr" json:"avg_speed"`
Direction string `xml:"direction,attr" json:"direction"`
Time string `xml:"time,attr" json:"time"`
}
func main() {
rawXmlData := `
<?xml version="1.0" encoding="utf-8"?>
<tracks clid="020">
<track uuid="551" category="s" route="8" vehicle_type="trolleybus">
<point latitude="53.61491" longitude="55.90922" avg_speed="24" direction="270" time="13122022:072116"/>
</track>
<track uuid="552" category="s" route="6" vehicle_type="trolleybus">
<point latitude="53.68321" longitude="57.90922" avg_speed="42" direction="181" time="13122022:072216"/>
</track>
</tracks>
`
var tracks Tracks
err := xml.Unmarshal([]byte(rawXmlData), &tracks)
if err != nil {
log.Fatal(err)
}
jsonData, err := json.Marshal(tracks)
if err != nil {
log.Fatal(err)
}
fmt.Printf(string(jsonData))
}
但是,不幸的是,它不起作用。我在控制台中得到以下错误:
2009/11/10 23:00:00 expected element type <tracks> but have <track>
我做错了什么?我该如何解决这个问题?
英文:
I was tasked with writing a Go utility that takes an XML file, parses it, and returns it in JSON.
Here is an example of the XML:
<?xml version="1.0" encoding="utf-8"?>
<tracks clid="020">
<track uuid="551" category="s" route="8" vehicle_type="trolleybus" >
<point
latitude="53.61491"
longitude="55.90922"
avg_speed="24"
direction="270"
time="13122022:072116"
/>
</track>
<track uuid="552" category="s" route="6" vehicle_type="trolleybus">
<point
latitude="53.68321"
longitude="57.90922"
avg_speed="42"
direction="181"
time="13122022:072216"
/>
</track>
</tracks>
I wrote the following code:
package main
import (
"encoding/json"
"encoding/xml"
"fmt"
)
type Tracks struct {
XMLName xml.Name `xml:"tracks" json:"-"`
Clid string `xml:"clid,attr" json:"clid"`
Tracks []Track `xml:"track" json:"track_list"`
}
type Track struct {
XMLName xml.Name `xml:"tracks"`
Uuid string `xml:"uuid,attr" json:"uuid"`
Category string `xml:"category,attr" json:"category"`
Route string `xml:"route,attr" json:"route"`
VehicleType string `xml:"vehicle_type,attr" json:"vehicle_type"`
Point Point `xml:"point" json:"point"`
}
type Point struct {
Latitude string `xml:"latitude,attr" json:"latitude"`
Longitude string `xml:"longitude,attr" json:"longitude"`
AvgSpeed string `xml:"avg_speed,attr" json:"avg_speed"`
Direction string `xml:"direction,attr" json:"direction"`
Time string `xml:"time,attr" json:"time"`
}
func main() {
rawXmlData := `
<?xml version="1.0" encoding="utf-8"?>
<tracks clid="020">
<track uuid="551" category="s" route="8" vehicle_type="trolleybus">
<point latitude="53.61491" longitude="55.90922" avg_speed="24" direction="270" time="13122022:072116"/>
</track>
<track uuid="552" category="s" route="6" vehicle_type="trolleybus">
<point latitude="53.68321" longitude="57.90922" avg_speed="42" direction="181" time="13122022:072216"/>
</track>
</tracks>
`
var tracks Tracks
err := xml.Unmarshal([]byte(rawXmlData), &tracks)
if err != nil {
log.Fatal(err)
}
jsonData, err := json.Marshal(tracks)
if err != nil {
log.Fatal(err)
}
fmt.Printf(string(jsonData))
}
But, unfortunately, it doesn't work. I get the following in the console:
2009/11/10 23:00:00 expected element type <tracks> but have <track>
What am I doing wrong? How can I solve this problem?
答案1
得分: 2
我觉得我会将讨论转移到一个答案上,因为我认为你很接近了。正如我之前提到的,你需要检查xml.Unmarshal
返回的错误。代码可能如下所示:
if err := xml.Unmarshal([]byte(rawXmlData), &tracks); err != nil {
panic(err)
}
现在你的代码中有有效的XML数据,我们可以生成有意义的错误;通过上述错误检查,运行你的代码会产生以下输出:
panic: expected element type <tracks> but have <track>
goroutine 1 [running]:
main.main()
/home/lars/tmp/go/main.go:48 +0x12f
这是因为你的数据结构中有一个小错误;在Track
结构体的定义中,你有:
type Track struct {
XMLName xml.Name `xml:"tracks"`
Uuid string `xml:"uuid,attr" json:"uuid"`
Category string `xml:"category,attr" json:"category"`
Route string `xml:"route,attr" json:"route"`
VehicleType string `xml:"vehicle_type,attr" json:"vehicle_type"`
Point Point `xml:"point" json:"point"`
}
你将XMLName
属性的标签错误地标记为tracks
,而应该是track
:
type Track struct {
XMLName xml.Name `xml:"track"`
Uuid string `xml:"uuid,attr" json:"uuid"`
Category string `xml:"category,attr" json:"category"`
Route string `xml:"route,attr" json:"route"`
VehicleType string `xml:"vehicle_type,attr" json:"vehicle_type"`
Point Point `xml:"point" json:"point"`
}
最后,这与问题没有直接关系,但你应该避免将变量命名为error
,因为那是内置的错误数据类型的名称。我会修改你对json.Marshal
的调用,如下所示:
jsonData, err := json.Marshal(tracks)
if err != nil {
panic(err)
}
你不需要在错误上使用panic()
;这只是一种方便的方式来退出代码。
在进行这些更改后,如果我们编译并运行代码,我们会得到以下输出(使用jq
格式化):
{
"clid": "020",
"track_list": [
{
"XMLName": {
"Space": "",
"Local": "track"
},
"uuid": "551",
"category": "s",
"route": "8",
"vehicle_type": "trolleybus",
"point": {
"latitude": "53.61491",
"longitude": "55.90922",
"avg_speed": "24",
"direction": "270",
"time": "13122022:072116"
}
},
{
"XMLName": {
"Space": "",
"Local": "track"
},
"uuid": "552",
"category": "s",
"route": "6",
"vehicle_type": "trolleybus",
"point": {
"latitude": "53.68321",
"longitude": "57.90922",
"avg_speed": "42",
"direction": "181",
"time": "13122022:072216"
}
}
]
}
请注意,你甚至不需要在结构体中使用XMLName
元素;如果我们完全删除它,使得结构体如下所示:
type Track struct {
Uuid string `xml:"uuid,attr" json:"uuid"`
Category string `xml:"category,attr" json:"category"`
Route string `xml:"route,attr" json:"route"`
VehicleType string `xml:"vehicle_type,attr" json:"vehicle_type"`
Point Point `xml:"point" json:"point"`
}
那么我们会得到以下输出(使用jq
格式化):
{
"clid": "020",
"track_list": [
{
"uuid": "551",
"category": "s",
"route": "8",
"vehicle_type": "trolleybus",
"point": {
"latitude": "53.61491",
"longitude": "55.90922",
"avg_speed": "24",
"direction": "270",
"time": "13122022:072116"
}
},
{
"uuid": "552",
"category": "s",
"route": "6",
"vehicle_type": "trolleybus",
"point": {
"latitude": "53.68321",
"longitude": "57.90922",
"avg_speed": "42",
"direction": "181",
"time": "13122022:072216"
}
}
]
}
英文:
I thought I would move the discussion to an answer, since I think you're pretty close. As I mentioned, you need to check the error returned by xml.Unmarshal
. That might look like this:
if err := xml.Unmarshal([]byte(rawXmlData), &tracks); err != nil {
panic(err)
}
Now that you have valid XML data in your code, we can produce meaningful errors; with the above error check in place, running your code produces:
panic: expected element type <tracks> but have <track>
goroutine 1 [running]:
main.main()
/home/lars/tmp/go/main.go:48 +0x12f
That's happening because of a minor typo in your data structures; in the definition of your Track
struct, you have:
type Track struct {
XMLName xml.Name `xml:"tracks"`
Uuid string `xml:"uuid,attr" json:"uuid"`
Category string `xml:"category,attr" json:"category"`
Route string `xml:"route,attr" json:"route"`
VehicleType string `xml:"vehicle_type,attr" json:"vehicle_type"`
Point Point `xml:"point" json:"point"`
}
You've mis-tagged the XMLName
attribute as tracks
when it should be track
:
type Track struct {
XMLName xml.Name `xml:"track"`
Uuid string `xml:"uuid,attr" json:"uuid"`
Category string `xml:"category,attr" json:"category"`
Route string `xml:"route,attr" json:"route"`
VehicleType string `xml:"vehicle_type,attr" json:"vehicle_type"`
Point Point `xml:"point" json:"point"`
}
Lastly -- and this isn't directly related to the problem -- you should avoid naming a variable error
, because that's the name of the built-in data type of errors. I would modify your call to json.Marshal
like this:
jsonData, err := json.Marshal(tracks)
if err != nil {
panic(err)
}
You don't need to panic()
on errors; this is just a convenient way to bail out of the code.
With these changes in place, if we compile and run the code we get as output (formatted with jq
):
{
"clid": "020",
"track_list": [
{
"XMLName": {
"Space": "",
"Local": "track"
},
"uuid": "551",
"category": "s",
"route": "8",
"vehicle_type": "trolleybus",
"point": {
"latitude": "53.61491",
"longitude": "55.90922",
"avg_speed": "24",
"direction": "270",
"time": "13122022:072116"
}
},
{
"XMLName": {
"Space": "",
"Local": "track"
},
"uuid": "552",
"category": "s",
"route": "6",
"vehicle_type": "trolleybus",
"point": {
"latitude": "53.68321",
"longitude": "57.90922",
"avg_speed": "42",
"direction": "181",
"time": "13122022:072216"
}
}
]
}
Note that you don't even need that XMLName
element in your structure; if we remove it completely so that we have:
type Track struct {
Uuid string `xml:"uuid,attr" json:"uuid"`
Category string `xml:"category,attr" json:"category"`
Route string `xml:"route,attr" json:"route"`
VehicleType string `xml:"vehicle_type,attr" json:"vehicle_type"`
Point Point `xml:"point" json:"point"`
}
Then we get as output (formatted with jq
):
{
"clid": "020",
"track_list": [
{
"uuid": "551",
"category": "s",
"route": "8",
"vehicle_type": "trolleybus",
"point": {
"latitude": "53.61491",
"longitude": "55.90922",
"avg_speed": "24",
"direction": "270",
"time": "13122022:072116"
}
},
{
"uuid": "552",
"category": "s",
"route": "6",
"vehicle_type": "trolleybus",
"point": {
"latitude": "53.68321",
"longitude": "57.90922",
"avg_speed": "42",
"direction": "181",
"time": "13122022:072216"
}
}
]
}
答案2
得分: 1
你好!以下是你要翻译的内容:
type Track struct {
XMLName xml.Name `xml:"tracks"`
应该是 "track" 而不是 "tracks"。
英文:
type Track struct {
XMLName xml.Name `xml:"tracks"`
should be "track" not "tracks"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论