RckMrkr
RckMrkr

Reputation: 1085

Golang: UnmarshalXMLAttr in encoding/xml

I'm trying to unmarshal some XML, where I want to parse the attributes in a special way. I have tried using the UnmarshalerAttr interface but I cannot get it working. Using the following code, the only output I get is '{Castle}'

package main

import (
    "encoding/xml"
    "fmt"
    "strings"
)

type Show struct {
    Title string `xml:"Title,attr"`
}

func (s *Show) UnmarshalXMLAttr(attr xml.Attr) error {
    fmt.Printf("Parsing attribute '%s', with value '%s'", attr.Name.Local, attr.Value)
    s.Title = strings.ToUpper(attr.Value)
    return nil
}

func main() {

    b := []byte(`<Series Title="Castle"></Series>`)

    var show Show
    xml.Unmarshal(b, &show)

    fmt.Println(show)
}

Any ideas?

Upvotes: 0

Views: 2110

Answers (1)

Not_a_Golfer
Not_a_Golfer

Reputation: 49187

The attribute unmarshaler needs to be the type of the title, not the show. here's a fixed version:

First, we create a "faux type" that just wraps string and implements the interface

type title string

Now we define the title field as our type, and not just a string.

This will call our unmarshaler for this attribute

type Show struct {
    Title title `xml:"Title,attr"`
}

And now the custom unmashaler for for our type:

func (s *title) UnmarshalXMLAttr(attr xml.Attr) error {
    fmt.Printf("Parsing attribute '%s', with value '%s'", attr.Name.Local, attr.Value)
    *s = title(strings.ToUpper(attr.Value))
    return nil
}

The rest remains the same:

func main() {

    b := []byte(`<Series Title="Castle"></Series>`)

    var show Show
    xml.Unmarshal(b, &show)

    fmt.Println(show)
}

http://play.golang.org/p/6J4UZ7BeG1

Upvotes: 2

Related Questions