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

问题描述:

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

例子:

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

我想写在Go一个脚本,让我到这个文件在多个较小的文件与每个文件的标签的特定数量分割。 所有关于如何用Go解析XML的例子似乎都依赖于知道文件中的元素。

可以在不知道该文件的情况下解析文件吗?对于XML中的每个元素来说,无论有什么元素(标题,项目,东西等等)都是这样的。

使用标准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 
     } 
    } 
} 
+0

关于如何区分文件结尾与实际错误的提示?有没有为EOF比较与定义的错误值?因为我处理错误与恐慌或日志。致命,这不是退出循环的最佳方式。 – Bunyk

+0

啊,不要紧,这只是我成为一个快乐的小菜。如果错误是'io.EOF'则断开循环,否则处理错误。 – Bunyk

这不是限制Go的极限。 XML元素根据其模式(它预先定义了其他元素中的元素)才有意义。

你应该看看SAX解析,像https://github.com/kokardy/saxlike

+0

你会给我一个例子吗?我给出的链接有示例和源代码。 不知道该文件可以被解析吗?是。对于XML中的每个元素来说,无论有什么元素(header,item,something等等) - YES。答案是问题的关键。 –

的功能似乎内置: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>[email protected]</Addr> 
      </Email> 
      <Email where='work'> 
       <Addr>[email protected]</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) 
} 
+2

解组对于* HUGE *文件不好。如果输入真的很大,他应该使用SAX解析器(任何人都是TB)?没有提到他特别要求该结构是未知的,并且您的代码具有硬编码结构。 –