LoginSignup
5
5

More than 5 years have passed since last update.

GoでXMLに未定義な要素が含まれていたらUnmarshalをエラーにしたい

Last updated at Posted at 2015-04-22

GoでWeb APIのXMLレスポンスのテストを書いているとき、「不要なXML要素が返却されていないか」というテスト項目が必要になりました。普通にGoのxml.Unmarshalを使っていると、構造体に未定義な要素は単に無視されてしまうので、工夫が必要です。

    // 余計な要素(XXX)が無視されてしまう例
    type Person struct {
        Name   string
        Gender string
        Age    int
    }

    badxml := []byte(`
  <Person>
    <Name>John</Name>
    <Gender>Male</Gender>
    <Age>20</Age>
    <XXX>xxxxxxxxxxx</XXX>
  </Person>`)

    p := Person{}
    if err := xml.Unmarshal(badxml, &p); err != nil {
        log.Fatal(err)
    }
    fmt.Println(p.Age) // -> 20 

encoding/xml パッケージで、,anyというフラグが定義されています。

* If the XML element contains a sub-element that hasn't matched any
of the above rules and the struct has a field with tag ",any",
unmarshal maps the sub-element to that struct field.

XML要素の中で、他のルールに適合しないサブ要素があるとき、",any"タグのついた構造体フィールドにマッピングされるそうです。これで余分なXML要素名を得る事が出来ます。

せっかくなので、これを応用して「XMLデコード中に余計な要素が現れたらエラーを返す型」を作ってみました。

type NoExtra struct {
        I noExtraInner `xml:",any"`
}

type noExtraInner struct{}

func (u *noExtraInner) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
        return xml.UnmarshalError(fmt.Sprint("detected an extra XML element. (", start.Name.Space, start.Name.Local, ")"))
}

このNoExtra型を下のように構造体フィールドに含めることで、Name,Age,Gender以外のXMLサブ要素が含まれている場合にxml.Unmarshal関数がエラーを返すことができます

Demo: http://play.golang.org/p/lJaBwq0Yry

type Person struct {
    Name   string
    Gender string
    Age    int
    NoExtra
}
    badxml := []byte(`
  <Person>
    <Name>John</Name>
    <Gender>Male</Gender>
    <Age>20</Age>
    <XXX>xxx</XXX>
  </Person>`)

    p := Person{}
    if err := xml.Unmarshal(badxml, &p); err != nil {
        log.Fatal(err) // -> detected an extra XML element. (XXX)
    }

こちらからは以上です。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5