go基础库之有效地解析大型XML文件

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.Tokenxml.Token是保存令牌类型的接口。 可以根据类型定义代码的行为。 示例代码测试解析的xml.StartElement是否是book元素之一。 然后它将数据部分解析为Book结构。 这样,Decoder中底层Reader中指针的位置被struct数据移位,并且解析可以继续。