XML은

2016-10-24 2 views
2

내가XML은

<table name="table1"> 
    <row> 
     <col name="col1">value</col> 
     <col name="col2">value</col> 
     <col name="col3">value</col> 
    </row> 
    ... 
</table> 
<table name="table2"> 
    <row> 
     <col name="col1">value</col> 
     <col name="col2">value</col> 
     <col name="col3">value</col> 
     <col name="col4">value</col> 
    </row> 
    ... 
</table> 

내가 xml.Decode() 기능으로 이동이 구문 분석을 시도하고 데이터베이스의 덤프에서 오는이 같은 XML 형식의이 (법인의 남용 속성)하지만 난 할 수 그러한 XML을 처리 할 수 ​​없습니다. 나는 Golang에서 검색된 XML 파싱 예제에서 찾은 몇 가지 예와 일치 시키려고했지만,이 종류의 형식 (엔티티 전체에 name 속성 포함)에는 적합하지 않습니다.

업데이트 답변

덕분에! 내가 성취하고자하는 것은 다음과 같습니다. "users"라는 테이블과 "categories"라는 테이블이 있다고 가정 해 봅시다. 해당 XML에서 시작하는 UserCategory 개체를 많이 생성하고 싶습니다. 첫 번째 답변을 기반으로 쉽게 Table 개체를 구문 분석 한 다음 내 자신의 개체를 만들 수는 있지만 건너 뛰고 내 개체를 직접 디코딩 할 수 있는지 알고 싶습니다.

답변

1

난 당신이 상대하고 있지만 XML 실제로 XML 값의 스트림과 같은 문제의 종류를 알 수없는, 그래서 당신은 그것을 디코딩해야합니다

type Table struct { 
    Name string `xml:"name,attr"` 
    Rows []Row `xml:"row"` 
} 

type Row struct { 
    Cols []Col `xml:"col"` 
} 

type Col struct { 
    Name string `xml:"name,attr"` 
    Value string `xml:",chardata"` 
} 

//... 

var err error 
dec := xml.NewDecoder(bytes.NewReader(b)) 
for err == nil { 
    t := Table{} 
    err = dec.Decode(&t) 
    fmt.Printf("%v, %+v\n", err, t) 
} 

놀이터 : https://play.golang.org/p/w4PqLv-Uc0.


편집 : 당신이 적절한 구조체에 직접적 XML을 디코딩 할 경우, 당신은 더 복잡한 장치가 필요합니다. 사용자를위한 예는 다음과 같습니다.

type User struct { 
    ID  int 
    Name string 
    Surname string 
} 

func (u *User) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { 
    var err error 

    type col struct { 
     Name string `xml:"name,attr"` 
     Value string `xml:",chardata"` 
    } 

    for { 
     c := col{} 
     err = d.Decode(&c) 
     if err != nil { 
      if err == io.EOF { 
       break 
      } 

      return err 
     } 
     switch c.Name { 
     case "id": 
      u.ID, err = strconv.Atoi(c.Value) 
      if err != nil { 
       return err 
      } 
     case "name": 
      u.Name = c.Value 
      continue 
     case "surname": 
      u.Surname = c.Value 
     } 
    } 

    return nil 
} 

type UserTable struct { 
    Users []User `xml:"row"` 
} 

놀이터 : https://play.golang.org/p/Hqta3Ngjo3.

+0

감사 :하며 (최소한의 작업 예를 들어 놀이터 링크를 참조 getNamename 속성을 반환하는 함수 임) 다음과 같은 뭔가. 나는 첫번째 질문에서 충분히 명확하지 않았으므로 좀 더 자세한 내용으로 편집했습니다. –

+0

@LeonardoRossi 편집을 참조하십시오. –

1

xml.Unmarshal() 함수의 doc은 XML 문서와 구조체 간의 매핑이 작동하는 방식을 설명합니다 (doc : json.Marshal() 보충). 구조 태그에 익숙하지 않은 경우이 대답을 확인하십시오. What are the use(s) for tags in Go?

먼저 XML 문서를 모델링해야합니다. 모든 다른 XML 문서 주위에 래퍼 XML 요소가 없으면 XML 문서가 아니라 여러 개의 XML 문서가 필요합니다. <table> 개의 문서가 여러 개 있습니다.

당신이처럼 모델링 할 수 있습니다

type Col struct { 
    Name string `xml:"name,attr"` 
    Value string `xml:",chardata"` 
} 

type Row struct { 
    Cols []Col `xml:"col"` 
} 

type Table struct { 
    Name string `xml:"name,attr"` 
    Rows []Row `xml:"row"` 
} 

을 그리고 여러 <table> 요소를 갖고 있기 때문에, 가장 쉬운 방법은 xml.Decoder()을 만들고 Decoder.Decode() 전화와 별도로 각을 구문 분석하는 것입니다 (Decoder.Decode()은 1 XML 문서를 구문 분석을 시도합니다 그것의 근원 독자).

이것은 그것을 할 수있는 방법입니다 :

d := xml.NewDecoder(strings.NewReader(data)) 
for { 
    var table Table 
    if err := d.Decode(&table); err != nil { 
     fmt.Println(err) 
     break 
    } 
    fmt.Printf("%+v\n", table) 
} 

소스 string에서 더 이상 데이터가없는 경우, Decoder.Decode()io.EOF를보고합니다.다음 data 문자열 위 대구 실행 :

const data = `<table name="table1"> 
    <row> 
     <col name="col1">value1</col> 
     <col name="col2">value2</col> 
     <col name="col3">value3</col> 
    </row> 
    <row> 
     <col name="col1">value4</col> 
     <col name="col2">value5</col> 
     <col name="col3">value6</col> 
    </row> 
</table> 
<table name="table2"> 
    <row> 
     <col name="col1">value7</col> 
     <col name="col2">value8</col> 
     <col name="col3">value9</col> 
     <col name="col4">valueA</col> 
    </row> 
</table>` 

출력은 다음과 같습니다

{Name:table1 Rows:[{Cols:[{Name:col1 Value:value1} {Name:col2 Value:value2} {Name:col3 Value:value3}]} {Cols:[{Name:col1 Value:value4} {Name:col2 Value:value5} {Name:col3 Value:value6}]}]} 
{Name:table2 Rows:[{Cols:[{Name:col1 Value:value7} {Name:col2 Value:value8} {Name:col3 Value:value9} {Name:col4 Value:valueA}]}]} 
EOF 

Go Playground에보십시오.

1

각 필드를 이름을 기준으로 다른 형식으로 비선형하려면 각 시작 요소 토큰을 가져 와서 이름을 확인한 다음 적절하게 디코딩해야합니다.

d := xml.NewDecoder(…) 
for { 
    tok, err := d.Token() 
    if err != nil { 
     log.Fatal(err) 
    } 

    start, ok := tok.(xml.StartElement) 
    if !ok { 
     // This is chardata or some other token. 
     // If it's bad XML, it will be caught on the next call to Token() 
     continue 
    } 
    switch getName(start) { 
    case "user": 
     u := &User{} 
     err = d.DecodeElement(u, &start) 
     if err != nil { 
      log.Fatal(err) 
     } 
     // Do whatever you want to do with your struct here. 
     fmt.Printf("Decoded a user: %+v\n", u) 
    case "category": 
     u := &Category{} 
     err = d.DecodeElement(u, &start) 
     if err != nil { 
      log.Fatal(err) 
     } 
     fmt.Printf("Decoded a category: %+v\n", u) 
    default: 
     // If the name is unrecognized, skip the rest of the element. 
     // We could also return an error 
     d.Skip() 
    } 
} 

https://play.golang.org/p/l7Vmj_8Igp