歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

使用Go解析超大XML文檔

我最近在處理Wiki百科的一些XML文件,有一些非常大的XML文件,例如最新的修訂版文件時36G(未壓縮)。關於解析XML,我曾經在幾種語言中做過實驗,最終我發現Go非常的適合。

Go擁有一個通用的解析XML的庫,也能很方便的編碼。一個比較簡單的處理XML的辦法是一次性將文檔解析加載到內存中,然而這中辦發對於一個36G的東西來講是不可行的。

我們也可以采用流的方式解析,但是一些在線的例子比較簡單而缺乏,這裡是我的解析wiki百科的示例代碼。(full example code at https://github.com/dps/go-xml-parse/blob/master/go-xml-parse.go)

這裡有其中的維基xml片段。

// <page>
//     <title>Apollo 11</title>
//      <redirect title="Foo bar" />
//     ...
//     <revision>
//     ...
//       <text xml:space="preserve">
//       {{Infobox Space mission
//       |mission_name=&lt;!--See above--&gt;
//       |insignia=Apollo_11_insignia.png
//     ...
//       </text>
//     </revision>
// </page>

在我們的Go代碼中,我們定義了一個結構體(struct)來匹配<page>元素。

type Redirect struct {
    Title string `xml:"title,attr"`
}

type Page struct {
    Title string `xml:"title"`
    Redir Redirect `xml:"redirect"`
    Text string `xml:"revision>text"`
}

現在我們告訴解析器wikipedia文檔包括一些<page>並且試著讀取文檔,這裡讓我們看看他如何以流的方式工作。其實這是非常簡單的,如果你了解原理的話--遍歷文件中的標簽,遇到<page>標簽的startElement,然後使用神奇的 decoder.DecodeElement API解組為整個對象,然後開始下一個。

decoder := xml.NewDecoder(xmlFile)

for {
    // Read tokens from the XML document in a stream.
    t, _ := decoder.Token()
    if t == nil {
        break
    }
    // Inspect the type of the token just read.
    switch se := t.(type) {
    case xml.StartElement:
        // If we just read a StartElement token
        // ...and its name is "page"
        if se.Name.Local == "page" {
            var p Page
            // decode a whole chunk of following XML into the
            // variable p which is a Page (se above)
            decoder.DecodeElement(&p, &se)
            // Do some stuff with the page.
            p.Title = CanonicalizeTitle(p.Title)
            ...
        }
...

我希望在你需要自己解析一個大的XML文件的時候,這些能節省你一些時間。

Copyright © Linux教程網 All Rights Reserved