2016-09-13 5 views
2

xml(業界標準)用のこの特定の形式があります。このxmlのサンプルを作成してサービスをテストできるようにする簡単なプログラムを作成しようとしています。私は標準のGo XMLライブラリを使用しています。Golang同じタグを使ったXML作成

問題は、XMLは面倒な形式です。

<Document> 
    <SubDocument> 
    {other fields} 
    <component> 
     <section> 
      <id value="0" valueType="num"/> //This is the part that differentiates the type of the section 
      <title>Foo-Type Section</title> 
      {other fields you lot don't need to care about} 
     </section> 
    </component> 
    <component> 
     <section> 
      <id value="1" valueType="num"/> 
      <title>Bar-Type Section</title> 
      {more fields you don't need to care about, but most are different than above} 
     </section> 
    </component> 
    {more sections} 
    </SubDocument> 
</Document> 

私は何に苦しんだことは行くには、各セクションのタグは、それらが異なる構造体の型である場合は一意である必要があるということです: は、ここでの簡易版です。

私は次のGoコードをしました:

type HasID struct{ 
    ID string `xml:"value,attr,omitempty"` 
    IDType string `xml:"valueType,attr,omitempty"` 
} 
type FooSection struct{ 
    ID HasID `xml:"id,omitempty"` 
    Title string `xml:"title,omitempty"` 
    //Foo fields 
} 
type BarSection struct{ 
    ID HasID `xml:"id,omitempty"` 
    Title string `xml:"title,omitempty"` 
    //Bar fields 
} 
type Document struct{ 
    XMLName struct{} `xml:"Document,omitempty"` 
    //Other fields 
    Sections []interface{} `xml:"SubDocument>component>section,omitempty"` 
} 

私もセクションのフィールドを持つようにしようとした何のタグを持っていないとFooSectionとBarSection両方がに、

XMLName struct{} `xml:"component>section,omitempty"` 

タグを持っています役立たず。さらに、Sectionsを文字列の配列にして、各セクションタイプをマーシャリングし、それらをダンプして "、innerxml"タグを使用しましたが、innerxmlの "<"などをエスケープします。

誰もがGoでこれを行う方法を知っていますか?構造体は私によって書かれており、必要に応じて変更するために完全に開いています。

私はあまりにもOOに固執していて、Goのような問題を抱えている可能性があります。

ありがとうございます!

+0

私はここでの質問をよく理解していません。 XMLを解析するのが問題なのですか? 「これはセクションのタイプを区別する部分です」というコメントがあります。違いの例を挙げることはできますか? – Kul

+0

このセクションのidの値を見ると、それは異なっています。 XML作成の手助けが必要でしたが、今解決しました。しかし、試してくれてありがとう! –

答えて

1

これは完璧な答えかどうかわかりませんが、それは実行可能です。要点はあなたが一時的な値にセクションの生データを非整列化し、これらはFooSectionまたはBarSection

にそれを非整列化したい場合に決定する前にそのIDを調べることUnmarshalXMLメソッド内で、その後Componentタイプにencoding/xml.Unmarshalerを実装することです私はComponentこと

type ID struct { 
    Value int `xml:"value,attr,omitempty"` 
    Type string `xml:"valueType,attr,omitempty"` 
} 

type Document struct { 
    Components []Component `xml:"SubDocument>component"` 
} 

type Component struct { 
    Section interface{} `xml:"section"` 
} 

type FooSection struct { 
    ID ID  `xml:"id"` 
    Title string `xml:"title"` 
    Foo string `xml:"foo"` 
} 

type BarSection struct { 
    ID ID  `xml:"id"` 
    Title string `xml:"title"` 
    Bar string `xml:"bar"` 
} 

注意して働いているタイプは、そのSectionとしてだけinterface{}を記憶しています。それはあなたがおそらくそれを使って何かをより良くすることができるように、あなたがそれを使いたいときにいつでもそれをタイプしなければならないので、それはちょっと面倒です。

その後UnmarshalXML方法はこちら

func (c *Component) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { 

    // tmp holds the data for this Component. We can only call d.DecodeElement 
    // once so we have to put it somewhere so it can be reused. 
    tmp := struct { 
     Data []byte `xml:",innerxml"` 
    }{} 
    if err := d.DecodeElement(&tmp, &start); err != nil { 
     return err 
    } 

    // which holds just enough information to tell us what kind of section to 
    // make. We'll unmarshal tmp.Data into this to inspect it 
    which := struct { 
     ID ID `xml:"id"` 
    }{} 
    if err := xml.Unmarshal(tmp.Data, &which); err != nil { 
     return err 
    } 

    switch which.ID.Value { 
    case 0: 
     var f FooSection 
     if err := xml.Unmarshal(tmp.Data, &f); err != nil { 
      return err 
     } 
     c.Section = f 

    case 1: 
     var b BarSection 
     if err := xml.Unmarshal(tmp.Data, &b); err != nil { 
      return err 
     } 
     c.Section = b 
    } 

    return nil 
} 

全作業コードon the playgroundです。


編集:これらのタイプは、実際に尋ねていたとおりにXMLストリングを生成するためにも機能するはずです。 Componentを作成するときは、作成するセクションの種類を選択してそこに貼り付けるだけです。それはinterface{}なので、何でも保持できます。これらのタイプを文字列に戻すことが期待どおりに動作することを示す例に私の遊び場のリンクを更新しました。

+0

私は構造体からXMLを作成する必要がありますが、別の方法で作成する必要はありません。 –

+0

@ L.D。ああ、ええ、すみません、私はそれを逃しました。まあ、私はそれらの型を持っているように、それはまだXMLを作るために動作する必要がありますように見えます。私はそれを示すために少し追加します。 – jcbwlkr

+0

ありがとう!幸いなことに、XMLの実際の解析はC#でXPathで処理されます。これは主にテストハーネスです。 –

関連する問題