英文:
<nil> when parsing xml string in golang
问题
我想使用golang解析xml。作为一个新手,我已经阅读了一些网上的文章,解释了如何解析XML,但我不确定为什么在这种情况下我的返回值是nil。
package main
import (
"fmt"
"encoding/xml"
)
func check(e error) {
if e != nil {
panic(e)
}
}
type Books struct {
XMLName xml.Name `xml:"Books"`
BookList []Book `xml:"Books>Book"`
}
type Book struct {
Title string `xml:"title,attr"`
Author string
Published string
}
func main() {
var data = []byte(`
<Books>
<Book title="A Brief History of Time" author="Stephen Hawking" published="1988">
<title>title here</title>
A Brief History of Time: From the Big Bang to Black Holes is a 1988 popular-science book by British physicist Stephen Hawking. It became a bestseller and sold more than 10 million copies in 20 years.
</Book>
<Book title="Steve Jobs" author="Walter Isaacson" published="2011">
Steve Jobs is the authorized self-titled biography book of Steve Jobs. The book was written at the request of Jobs by Walter Isaacson, a former executive at CNN.
</Book>
</Books>
`)
b := Books{}
err := xml.Unmarshal([]byte(data), &b)
check(err)
fmt.Println(b)
}
以上是你提供的代码,已经进行了一些修改。请注意以下几点:
- 在
Book结构体中,将title字段的标签改为xml:"title,attr",以指示它是一个属性。 - 在
Books结构体中,将BookList字段的标签改为xml:"Books>Book",以指示它是Books元素下的Book元素列表。 - 在
main函数中,将xml.Unmarshal的返回值存储在变量err中,并通过调用check函数来检查错误。 - 打印解析后的结果
b。
希望这可以帮助你解决问题!
英文:
I would like to parse xml using golang. Being new to using go, I've read articles around the web, explaining how to parse XML but I'm not sure why my return value is nil in this case.
package main
import (
"fmt"
//"io/ioutil"
"encoding/xml"
)
func check(e error) {
if e != nil {
panic(e)
}
}
type Books struct {
XMLName xml.Name `xml:"Books"`
BookList []Book `xml:"Books>Book"`
}
type Book struct {
title string `xml:"title,attr"`
author string
published string
}
func main() {
//f, err := ioutil.ReadFile("xml/Books.xml")
//check(err)
var data = []byte(`
<Books>
<Book title="A Brief History of Time" author="Stephen Hawking" published="1988">
<title>title here</title>
A Brief History of Time: From the Big Bang to Black Holes is a 1988 popular-science book by British physicist Stephen Hawking. It became a bestseller and sold more than 10 million copies in 20 years.
</Book>
<Book title="Steve Jobs" author="Walter Isaacson" published="2011">
Steve Jobs is the authorized self-titled biography book of Steve Jobs. The book was written at the request of Jobs by Walter Isaacson, a former executive at CNN.
</Book>
</Books>
`)
b := Books{}
o := xml.Unmarshal([]byte(data), &b)
fmt.Println(o)
}
答案1
得分: 2
我将调试反馈放在了注释中,但我刚刚修改了你的示例使其可以工作,并且可以在这里进行测试:https://play.golang.org/p/_UIph2je7f
package main
import (
"fmt"
// "io/ioutil"
"encoding/xml"
)
func check(e error) {
if e != nil {
panic(e)
}
}
type Books struct {
XMLName xml.Name `xml:"Books"`
BookList []Book `xml:"Book"`
}
type Book struct {
Title string `xml:"title,attr"`
Author string `xml:"author,attr"`
Published string `xml:"published,attr"`
}
func main() {
// f, err := ioutil.ReadFile("xml/Books.xml")
// check(err)
var data = []byte(`
<Books>
<Book title="A Brief History of Time" author="Stephen Hawking" published="1988">
<title>title here</title>
A Brief History of Time: From the Big Bang to Black Holes is a 1988 popular-science book by British physicist Stephen Hawking. It became a bestseller and sold more than 10 million copies in 20 years.
</Book>
<Book title="Steve Jobs" author="Walter Isaacson" published="2011">
Steve Jobs is the authorized self-titled biography book of Steve Jobs. The book was written at the request of Jobs by Walter Isaacson, a former executive at CNN.
</Book>
</Books>
`)
b := Books{}
o := xml.Unmarshal([]byte(data), &b)
fmt.Println(o)
fmt.Println(b)
}
以下是我所做的四个更改的概述:
1)打印Unmarshal返回的Books对象,而不是错误。
2)将Book中的字段的首字母大写,使它们成为“可导出”的,以便其他包可以获取/设置它们(在这种情况下是解组器)。
3)添加XML属性。通过导出字段,可以避免隐式字符串匹配,因此您需要明确指定将读入每个字段的XML值。
4)更新BookList的XML路径。你说它应该是Books>Book,但这意味着在你的XML中存在另一层嵌套。这个对象是Books,你想要的列表中的元素的相对XPath只是Book,所以你在那里放置了它。
英文:
I put the debugging feedback in a comment but I've just modified your example to work and it can be tested here; https://play.golang.org/p/_UIph2je7f
package main
import (
"fmt"
//"io/ioutil"
"encoding/xml"
)
func check(e error) {
if e != nil {
panic(e)
}
}
type Books struct {
XMLName xml.Name `xml:"Books"`
BookList []Book `xml:"Book"`
}
type Book struct {
Title string `xml:"title,attr"`
Author string `xml:"author,attr"`
Published string `xml:"published,attr"`
}
func main() {
//f, err := ioutil.ReadFile("xml/Books.xml")
//check(err)
var data = []byte(`
<Books>
<Book title="A Brief History of Time" author="Stephen Hawking" published="1988">
<title>title here</title>
A Brief History of Time: From the Big Bang to Black Holes is a 1988 popular-science book by British physicist Stephen Hawking. It became a bestseller and sold more than 10 million copies in 20 years.
</Book>
<Book title="Steve Jobs" author="Walter Isaacson" published="2011">
Steve Jobs is the authorized self-titled biography book of Steve Jobs. The book was written at the request of Jobs by Walter Isaacson, a former executive at CNN.
</Book>
</Books>
`)
b := Books{}
o := xml.Unmarshal([]byte(data), &b)
fmt.Println(o)
fmt.Println(b)
}
Here's a rundown of the four changes I made;
-
print the
Booksobject instead of the err returned fromUnmarshal -
uppercase the first letter of fields on
Bookto make them 'exported' so they can be get/set by other packages (the unmarshaller in this case) -
add xml attributes. In exporting the fields it makes it so there isn't an implicit string match so you gotta explicitly specify which xml value is read into each field
-
update the XML path for
BookListfor this you said it would be Books>Book but that implies another level of nesting that didn't exist in your xml. This object isBooks, the elements you want in that list would have a relative xpath of simplyBookso that's what you put there.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论