golang xml解析

第二章里还提到了xml的解析部分。之前有想整理下encoding包下常用的几个文件格式的处理。这次刚好整理下xml的部分.先上例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package main
import (
"bytes"
"encoding/xml"
"fmt"
"os"
)
type rss2 struct {
XMLName xml.Name `xml:"rss"`
ChannelDoc channel `xml:"channel"`
}
type channel struct {
XMLName xml.Name `xml:"channel"`
Title string `xml:"title"`
Description string `xml:"description"`
Link string `xml:"link"`
He string `xml:"heh"`
Item []item `xml:"item"`
}
type item struct {
XMLName xml.Name `xml:"item"`
Title string `xml:"title"`
Guid guid `xml:"guid"`
}
type guid struct {
GuidValue string `xml:",chardata"`
GuidAttr string `xml:"isPermaLink,attr"`
}
func () {
s := `<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>RSS Title</title>
<description>This is an example of an RSS feed</description>
<link>http://www.example.com/main.html</link>
<lastBuildDate>Mon, 06 Sep 2010 00:01:00 +0000 </lastBuildDate>
<pubDate>Sun, 06 Sep 2009 16:20:00 +0000</pubDate>
<ttl>1800</ttl>
<item>
<title>Example entry</title>
<description>Here is some text containing an interesting description.</description>
<link>http://www.example.com/blog/post/1</link>
<guid isPermaLink="true">7bd204c6-1655-4c27-aeee-53f933c5395f</guid>
<pubDate>Sun, 06 Sep 2009 16:20:00 +0000</pubDate>
</item>
<item>
<title>Example entry2</title>
<description>Here is some text containing an interesting description.</description>
大专栏  golang xml解析"> <link>http://www.example.com/blog/post/12</link>
<guid isPermaLink="true">7bd204c6-1655-4c27-aeee-53f933c53952f</guid>
<pubDate>Sun, 06 Sep 2009 16:20:00 +0000</pubDate>
</item>
</channel>
</rss>`
st := new(rss2)
err := xml.NewDecoder(bytes.NewBuffer([]byte(s))).Decode(st)
if err == nil {
fmt.Println(st)
} else {
fmt.Println(err)
}
err = xml.NewEncoder(os.Stdout).Encode(st)
fmt.Println()
st2 := new(rss2)
err = xml.Unmarshal([]byte(s), st2)
if err == nil {
fmt.Println(st2)
}
result, _ := xml.Marshal(st2)
fmt.Println(string(result))
fmt.Println(st2.ChannelDoc.Item[0].Guid.GuidAttr)
}

(代码里的xml来自rss wiki示例)

首先将xml 解析成指定的interface{},这里则是以struct作为例子。
既然是struct,首先提下映射规则。首先struct的字段必须是可导出的。第二tag的优先级是最高的。就是代码里的

1
`xml:"rss"`

这些内容,然后他也会根据可导出的字段名来映射。当然如果想要忽略部分字段只需要在tag里写”-“即可
比如上面代码里的He这个字段,这是一个干扰项,xml里并没有对应的节点,虽然他并不会解析出内容,但是在还原成xml时他是会占用heh这个节点的。只需要改成xml:"-"在还原的xml里就不会看到这个字段了(当然这样写就不对,都是根据数据来定义struct的,这里只是举个例子)。
至于优先级的问题,就比如

1
GuidAttr string `xml:"isPermaLink,attr"`

这个字段的定义。他是获取guid节点中的isPermaLink这个attribution.还原后的自然是isPermaLink而不是GuidAttr.
同理的还有rss2 这个typeName.不过这里有些特殊:XMLName以及类型xml.Name是固定写法,是来指定根节点的。这里也是故意写成rss2,对应的节点是rss.在tag的作用下还原后是rss.不然的话会是rss2.因为没有XMLName的话会根据类型名做转换。
还有就是,chardata这个写法.这是来获取value值的。

接下来就是方法的解释了

1
func Unmarshal(data []byte, v interface{}) error

这个方法很简单,src是byte数组,dst是interface{}.这里自然是struct.(这里使用指针是因为后面需要将其作为对象操作,查看其值,不然用过后就抛弃了,无法操作)
返回一个error这个方法没什么好说的。
对应的方法是Marshal.

1
func Marshal(v interface{}) ([]byte, error)

同理,与Unmarshal对应即可

1
2
3
4
5
func NewDecoder(r io.Reader) *Decoder
func NewEncoder(w io.Writer) *Encoder
func (d *Decoder) Decode(v interface{}) error
func (enc *Encoder) Encode(v interface{}) error

这里是对应的两组方法。上面则是返回对应的struct.参数只要是符合io.Reader以及io.Writer接口即可。分别做数据源读入以及输出。这里就简单用buffer和stdout举例了。
构造完成之后则调用对应的编解码方法即可。
其实解析的方法很简单,主要是映射关系的管理。简单应用应该就是像上面所写的那样了。还有就是今天群里有大神语音解惑,但是因为个人水平问题,听的很懵。很气但是无可奈何。自己mark下。我还会回去的,到时候一定可以听懂的!

原文地址:https://www.cnblogs.com/lijianming180/p/12302430.html