2016-04-14 22 views
3

Çeşitli öğelere sahip olan büyük bir XML dosyasını nasıl ayrıştırırsınız (ör., Aynı öğe birden çok kez tekrarlanmıyor).Go'da çeşitli öğelerle büyük XML dosyası nasıl ayrıştırılır?

Örnek:

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

bana dosya başına etiketleri belirli miktarda birden fazla küçük dosyalarda bu dosyayı bölmek olanak sağlayacak git bir senaryo yazmak istiyorum. XML'i Git ile nasıl ayrıştırılacağına dair tüm örnekler, dosyada sahip olduğunuz öğeleri bilmeye güveniyor gibi görünüyor.

Dosya bunu bilmeden ayrıştırılabilir mi? XML'deki her öğe için bir şey ne olursa olsun (başlık, öğe, bir şey vs.)

cevap

9

Kullanım standart xml Decoder: https://golang.org/pkg/encoding/xml/#Unmarshal

gibi bir şey deneyin.

Simgeleri tek tek okumak için Token'u arayın. Bir ilgilenilen başlangıç ​​elemanı bulunduğunda, öğeyi bir Go değerine deşifre etmek için DecodeElement numaralı telefonu arayın. İşte

dekoder nasıl kullanılacağına ilişkin bir taslak verilmiştir: "? Nasıl programının" Ben sorarsanız

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

Dosyanın sonunu gerçek hatadan ayırt etmenin nasıl bildiklerine dair ipuçları var mı? EOF ile karşılaştırmak için bazı tanımlanmış hata değerleri var mı? Çünkü panik veya log.Fatal ile hataları ele alıyorum ve bu döngülerden çıkmak için en iyi yol değildir. – Bunyk

+0

Ah, boşver, sadece benim bir şey değil. Hata "io.EOF" hatası ise, hata işlemez. – Bunyk

1

Bu, Xml sınırı olarak Go'nun bir sınırı değildir. XML öğeleri sadece şemalarına göre anlamlıdır (hangi elemanların diğer elemanlarda olduğunu önceden belirler). SAX için bakmak gerekir

1
+0

bana bir örnek verebilir misin? Verdiğim bağlantıda örnek ve kaynak kodları var. Dosya bunu bilmeden ayrıştırılabilir mi? EVET. XML'deki her eleman için ne gibi bir unsur olursa olsun (başlık, öğe, bir şey, vb ...) - EVET. Cevap, soru yönündedir. –

0

gibi bir şey, ayrıştırır işlevselliği görünüyor yerleşiktir:

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

Unmarshalling, * BÜYÜK * dosyaları için kötü olurdu. Bir girdi gerçekten büyükse bir SAX çözümleyici kullanmalıdır (terabayt kimse?). Özellikle, yapının bilinmediğini ve kodunuzun sabit kod yapısına sahip olmasını istemediğini belirtmekten çekinmeyin. –

İlgili konular