2016-04-14 9 views
3

さまざまな要素(つまり、同じ要素が複数回繰り返されていない)を持つ巨大なXMLファイルを解析するにはどうすればよいですか。Goのさまざまな要素を持つ巨大なXMLファイルを解析する方法は?

例:

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

私は私がファイルごとにタグの具体的な量で複数の小さなファイルで、このファイルを分割することができるようになる移動でスクリプトを書きたいです。 Goを使ってXMLを解析する方法に関するすべての例は、ファイル内にある要素を知ることに依存しているようです。

これを知らずにファイルを解析することはできますか?どの要素(ヘッダー、アイテム、何かなど)に関係なく、XMLの各要素のようなもの

答えて

9

標準xml Decoderを使用します。

トークンを1つずつ読み込むには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と比較するために定義されたエラー値がありますか?私はパニックやlog.Fatalでエラーを処理するので、これはループを終了する最良の方法ではありません。 – Bunyk

+0

ああ、決して私が行くことの騒ぎであることは気にしないでください。エラーが 'io.EOF'の場合はループを中断し、それ以外の場合はエラーを処理します。 – Bunyk

1

これはxmlの制限としてあまり制限されていません。 XML要素は、そのスキーマ(他の要素に含まれる要素を事前定義する)に従ってのみ意味を持ちます。あなたがSAXになります

1
+0

をあなたは私に例をコードしますか?私が与えたリンクには例とソースコードがあります。 これを知らずにファイルを解析することはできますか?はい。どの要素があっても、XMLの各要素のようなもの(ヘッダー、項目、何かなど) - はい。答えは問題の点です。 –

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>[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パーサを使用する必要があります(誰でもテラバイトですか?)。彼は具体的に構造が不明であり、コードにハードコードの構造体があることを特に要求していません。 –

関連する問題