Reputation: 3180
I have an XML document. Some fields have custom format. Example:
<document>
<title>hello world</title>
<lines>
line 1
line 2
line 3
</lines>
</document>
I want to import it into structure like:
type Document struct {
Title string `xml:"title"`
Lines []string `xml:"lines"`
}
Is there some way how to implement custom decoder, which will split lines string into array of lines (["line 1", "line 2", "line 3"]
)?
Its possible to make Lines field a string type and make split after xml import, but it doesn't seems to be very elegant solution. Is there any way i can define custom decoder for line spliting and combine it with xml decoder?
Upvotes: 4
Views: 3335
Reputation: 4373
Here is a spelled out example of what CSE is suggesting:
type Document struct {
Title string `xml:"title"`
LineData string `xml:"lines"`
}
func (d *Document)Lines() []string {
return strings.Split(d.LineData, '\n')
}
This is similar to what net/http Request does: read the data into a struct, and then provide accessors to interpret that struct.
If you really don't want to do that, then another approach that I have used is to create two structs. Read the raw data into the first and then use that to construct the second.
If you are planning on shipping this out as JSON or some other wire format, the second struct could just be a map.
func (d *Document) Map() map[string]interface{} {
m := make(map[string]interface{})
m["lines"] = strings.Split(d.LineData, '\n')
m["title"] = d.Title
return m
}
Upvotes: 0
Reputation: 43949
You can achieve this by defining a new type that conforms to the xml.Unmarshaler
interface. So rather than making Lines
a []string
, declare a new type with an appropriate UnmarshalXML
method. For instance:
type Lines []string
func (l *Lines) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var content string
if err := d.DecodeElement(&content, &start); err != nil {
return err
}
*l = strings.Split(content, "\n")
return nil
}
You can see a full example here: http://play.golang.org/p/3SBu3bOGjR
If you want to support encoding this type too, you can implement the MarshalXML
method in a similar fashion (construct the string content you want and pass that to the encoder).
Upvotes: 7