XML是一种非常常见的数据交换格式。Go库包含对以与JSON相同的方式解析XML文件的支持。通常,使用与XML方案对应的结构,并且在此帮助下,一次解析XML内容。问题是当XML文件太大而无法容纳到内存中时,需要以块的形式解析文件。本文将展示如何处理大型XML文件并解析所需信息。
有效地解析大型XML文件
Golang 版本
1.12.1
前沿
XML是一种非常常见的数据交换格式。Go库包含对以与JSON相同的方式解析XML文件的支持。通常,使用与XML方案对应的结构,并且在此帮助下,一次解析XML内容。问题是当XML文件太大而无法容纳到内存中时,需要以块的形式解析文件。本文将展示如何处理大型XML文件并解析所需信息。
实现
创建文件data.xml
,内容如下:
<?xml version="1.0"?>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
<book id="bk112">
<author>Galos, Mike</author>
<title>Visual Studio 7: A Comprehensive Guide</title>
<genre>Computer</genre>
<price>49.95</price>
<publish_date>2001-04-16</publish_date>
<description>Microsoft Visual Studio 7 is explored
in depth, looking at how Visual Basic, Visual C++, C#,
and ASP+ are integrated into a comprehensive development
environment.</description>
</book>
</catalog>
创建文件xml.go
,代码如下:
package main
import (
"encoding/xml"
"fmt"
"os"
)
type Book struct {
Title string `xml:"title"`
Author string `xml:"author"`
}
func main() {
f, err := os.Open("data.xml")
if err != nil {
panic(err)
}
defer f.Close()
decoder := xml.NewDecoder(f)
// 逐一阅读本书
books := make([]Book, 0)
for {
tok, _ := decoder.Token()
if tok == nil {
break
}
switch tp := tok.(type) {
case xml.StartElement:
if tp.Name.Local == "book" {
// 将元素解码为struct
var b Book
decoder.DecodeElement(&b, &tp)
books = append(books, b)
}
}
}
fmt.Println(books)
}
$ go run xml.go
[{XML Developer's Guide Gambardella, Matthew} {Visual Studio 7: A Comprehensive Guide Galos, Mike}]
原理
使用xml
包的NewDecoder
函数,可以创建XML内容的Decoder
。
通过在Decoder
上调用Token
方法,接收xml.Token
。 xml.Token
是保存令牌类型的接口。 可以根据类型定义代码的行为。 示例代码测试解析的xml.StartElement
是否是book
元素之一。 然后它将数据部分解析为Book
结构。 这样,Decoder
中底层Reader
中指针的位置被struct数据移位,并且解析可以继续。