XML in Go

在Go的标准包里包含一个xml包来处理xml文件“encoding/xml", 我们可以载入它来对xml进行操作。

首先我们先建立一个xml(Person.xml)

<Person>
    <FullName>Grace R. Emlin</FullName>
    <Company>Example Inc.</Company>
    <Email where="home">
        <Addr>gre@example.com</Addr>
    </Email>
    <Email where='work'>
        <Addr>gre@work.com</Addr>
    </Email>
    <Group>
        <Value>Friends</Value>
        <Value>Squash</Value>
    </Group>
    <City>Hanga Roa</City>
    <State>Easter Island</State>
</Person>

a. xml对应struct的构造

接下来我们需要给这个xml文件建立一个与我们解析后对应的xml对象,而这个对象我们可以用struct来构造。这个对象的结构是不用和xml的原来的结构一直,可以根据自己的需求

做自定义。我一开始对这个不是很适应觉得很麻烦,但后来发现可以相当灵活的控制xml对象。先给出一个定义,然后再一句一句的解释。

 1 type Email struct {
 2     Where string `xml:"where,attr"`
 3     Addr  string
 4 }
 5 
 6 type Address struct {
 7     City, State string
 8 }
 9 
10 type Result struct {
11     XMLName xml.Name `xml:"Person"`
12     Name    string   `xml:"FullName"`
13     Phone   string
14     Email   []Email15     Groups  []string `xml:"Group>Value"`
16     Address
17 }

 

Line 1-4:  我们把<Email>节点作为一个struct,它包含了2个字段分别是Where,Addr。

         Where: 读取的是Email节点的属性值,在字段定义的最后用`xml:"where,attr"`表示。

         Addr:读取的是Email节点下的<Addr>的值,需要注意的是字段的名字要和xml文件的里的字段大小写一致。

              这样可以不需要再声明一个Addr的struct就可以直接映射了。

Line 6-8:  这里我们定义了一个Address的struct,但是在xml里并没有对应的节点。但是Address里的值是把xml里的City和State组合在一起了。

Line 10-17:  定义了一个总的struct来描述整个xml。

       XMLName:它的字段的类型是xml.Name,说明了xml的名字

       Name:在xml里并没有Name的节点,但是在后面`xml:"FullName"`我们指明了它是映射到FullName节点上的值

       Phone:更进一步了,在整个xml里没有Phone节点,而且我们也没用给出任何映射。这样我们把xml读到内存中时就对它进行了一些“改造”,很灵活吧。

       Email:需要注意的是这里的类型用的Email,正好是我们先前定义的类型,而且是[]说明会有多个。

                    Groups:这个也很有意思,">"说明的是子元素,这里指的是Group节点下的子节点Value。

       Address:直接用了我们上面定义的Address,没有类型指定。

Note:另外需要说明的是struct里的字段必须是大写时才能被解析。

对于xml属性定义的具体规则可以在这里查询:http://golang.org/pkg/encoding/xml/

KO。到这里我们的准备已经做好了剩下的就是来解析我们的xml。至于解析xml我目前知道两种:xml.Unmarshal() 和 decoder

先说第一种,xml.Unmarshal()是xml包里提供的方法:

var v Result
xmlFile, err := ioutil.ReadFile("Person.xml") if err != nil { fmt.Println("Error opening file: ", err) return } err1 := xml.Unmarshal(xmlFile, &v) if err1 != nil { fmt.Printf("error: %v", err) return }

Note:需要注意的是这里需要传入指针&v

第二种情况我们用流的形式来解析,用这种方式我们可以很容易的处理大数据的xml。

xmlFile, err := os.Open("Person.xml")
if err != nil {
    fmt.Println("Error opening file: ", err)
    return
}
defer xmlFile.Close()
decoder := xml.NewDecoder(xmlFile)
for {
    t, _ := decoder.Token()
    if t == nil {
        break
    }
    switch se := t.(type) {
    case xml.StartElement:
        if se.Name.Local == "Person" {
            var d Result
            decoder.DecodeElement(&d, &se)
            fmt.Println(d)
        }
    }
}

Note:t.(type)的用法只能在switch的类型遍历中使用,具体可以参考:http://golang.org/doc/effective_go.html#switch

 

Refference:

1. http://golang.org/pkg/encoding/xml

2. http://blog.davidsingleton.org/parsing-huge-xml-files-with-go/

转载于:https://www.cnblogs.com/yuanershi/archive/2013/01/29/2881192.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值