Nima Sarayan
Nima Sarayan

Reputation: 325

Add attribute to the child without generating new XML element

How can I create this XML using the Go XML package?

<Files><File width="200" height="100">somevaluehere</File></Files>

It is harder than you may think, for example:

type Video struct {
    Files Files `xml:"Files"`
}

type Files struct {
    Width  string `xml:"Width,attr"`
    Height string `xml:"Height,attr"`
    File   string `xml:"File"`
}

the output is:

<Video><Files Width="640" Height="480"><File>somevalue</File></Files></Video>

And I want:

<Video><Files><File Width="640" Height="480">somevalue</File></Files></Video>

Upvotes: 1

Views: 271

Answers (1)

icza
icza

Reputation: 417827

You want Video.Files to be rendered into <Video><Files><File> tag, so indicate this in the tag:

type Video struct {
    Files Files `xml:"Files>File"`
}

And you want the Files.File value to be the tag's char data, also indicate this in the tag:

type Files struct {
    Width  string `xml:"Width,attr"`
    Height string `xml:"Height,attr"`
    File   string `xml:",chardata"`
}

Testing it:

v := Video{
    Files: Files{
        Width:  "640",
        Height: "480",
        File:   "someValue",
    },
}
out, err := xml.Marshal(v)
if err != nil {
    panic(err)
}
fmt.Println(string(out))

Which outputs (try it on the Go Playground):

<Video><Files><File Width="640" Height="480">someValue</File></Files></Video>

If there could me multiple <File> elements inside <Files>, I would make Video.Files a slice:

type Video struct {
    Files []File `xml:"Files>File"`
}

type File struct {
    Width  string `xml:"Width,attr"`
    Height string `xml:"Height,attr"`
    File   string `xml:",chardata"`
}

Testing it:

v := Video{
    Files: []File{
        {
            Width:  "640",
            Height: "480",
            File:   "someValue",
        },
        {
            Width:  "320",
            Height: "240",
            File:   "otherValue",
        },
    },
}
out, err := xml.Marshal(v)
if err != nil {
    panic(err)
}
fmt.Println(string(out))

Which outputs (try it on the Go Playground):

<Video><Files><File Width="640" Height="480">someValue</File><File Width="320" Height="240">otherValue</File></Files></Video>

Upvotes: 2

Related Questions