如何使用Go中的各种元素解析巨大的XML文件?

时间:2016-04-14 13:56:27

标签: go

如何解析具有各种元素的巨大XML文件(即不重复多次相同的元素)。

示例:

<stuff>
    <header>...</header>
    <item>...</item>
    ...
    <item>...</item>
    <something>...</sometihng>
</stuff>

我想在Go中编写一个脚本,允许我将该文件拆分为多个较小的文件,每个文件都有特定数量的标签。 有关如何使用Go解析XML的所有示例似乎都依赖于了解文件中的元素。

可以在不知道的情况下解析文件吗?对于XML中的每个元素都有类似的东西,无论那里有什么元素(标题,项目,等等......)

5 个答案:

答案 0 :(得分:12)

使用标准xml Decoder

致电Token逐一阅读令牌。找到感兴趣的起始元素后,调用DecodeElement将元素解码为Go值。

以下是如何使用解码器的草图:

d := xml.NewDecoder(r)
for {
    t, tokenErr := d.Token()
    if tokenErr != nil {
        if tokenErr == io.EOF {
           break
        }
        // handle error
    }
    switch t := t.(type) {
    case xml.StartElement:
        if t.Name.Space == "foo" && t.Name.Local == "bar" {
            var b bar
            if err := d.DecodeElement(&b, &t); err != nil {
                // handle error
            }
            // do something with b
        }
    }
}

答案 1 :(得分:1)

这不是Go作为xml限制的限制。 XML元素只根据其模式(预定义了其他元素中的元素)才有意义。

答案 2 :(得分:1)

您应该查看SAX解析,例如https://github.com/kokardy/saxlike

答案 3 :(得分:0)

功能似乎是内置的:https://golang.org/pkg/encoding/xml/#Unmarshal

尝试类似:

package main

import (
    "encoding/xml"
    "fmt"
)

func main() {
    type Email struct {
        Where string `xml:"where,attr"`
        Addr  string
    }
    type Address struct {
        City, State string
    }
    type Result struct {
        XMLName xml.Name `xml:"Person"`
        Name    string   `xml:"FullName"`
        Phone   string
        Email   []Email
        Groups  []string `xml:"Group>Value"`
        Address
    }
    v := Result{Name: "none", Phone: "none"}

    data := `
        <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>
    `
    err := xml.Unmarshal([]byte(data), &v)
    if err != nil {
        fmt.Printf("error: %v", err)
        return
    }
    fmt.Printf("XMLName: %#v\n", v.XMLName)
    fmt.Printf("Name: %q\n", v.Name)
    fmt.Printf("Phone: %q\n", v.Phone)
    fmt.Printf("Email: %v\n", v.Email)
    fmt.Printf("Groups: %v\n", v.Groups)
    fmt.Printf("Address: %v\n", v.Address)
}

答案 4 :(得分:0)

您还可以检查已通过大型xml文件测试的以下库。它已写成解决默认XML包中的性能issue

xml stream parser