Golang marshal dynamic xml element name
Asked Answered
I

2

7

The xml file consists of two elements. Those elements have the same structure except for one element name. I tried to set a value to the XMLName property, but that didn't work.

Xml:

<!-- first element -->
<PERSON>
  <ELEM1>...</ELEM1>
  <ELEM2>...</ELEM2>
  <ELEM3>...</ELEM3>
  <ELEM4>...</ELEM4>
</PERSON>


<!-- second element -->
<SENDER>
  <ELEM1>...</ELEM1>
  <ELEM2>...</ELEM2>
  <ELEM3>...</ELEM3>
  <ELEM4>...</ELEM4>
</SENDER>

Is it possible to define a struct such that the element name is dynamic?

type Person struct {
    XMLName string `xml:"???"` // How make this dynamic?
    e1 string `xml:"ELEM1"`
    e2 string `xml:"ELEM2"`
    e3 string `xml:"ELEM3"`
    e4 string `xml:"ELEM4"`
}
Immensity answered 11/11, 2014 at 14:40 Comment(0)
B
10

In the documentation, it says that the XMLName field must be of type xml.Name.

type Person struct {
    XMLName xml.Name
    E1 string `xml:"ELEM1"`
    // ...
}

Set the element name via the Local field of xml.Name:

person := Person { 
    XMLName: xml.Name { Local: "Person" },
    // ...
}

(Also, E1 - E4 must be exported in order to be included in the XML output).

Playground example: http://play.golang.org/p/bzSutFF9Bo

Betoken answered 11/11, 2014 at 14:52 Comment(5)
Ah, missed the part about using xml.Name instead of string. Thanks for the example!Immensity
Can you show an example of the opposite direction? How would you get the xml source into the struct?Immensity
The same XMLName field works with xml.Unmarshal: play.golang.org/p/8-uDgUHVlgBetoken
Ok, that works for me, too. But what I can't get to work is to marshal a slice and the unmarshal it back: play.golang.org/p/7uxsuMnGxW Am I missing something?Immensity
I think you need a parent XML element (and an enclosing struct) to encode/decode a slice of values. See play.golang.org/p/hJLJZP-jcH (also note the ",any" tag).Betoken
P
3

I found a lighter solution for this case where you only need to set the struct tag for XMLName field like this:

type Person struct {
    XMLName xml.Name `xml:"Person"`
    E1 string        `xml:"ELEM1"`
    // ...
}
Plagioclase answered 8/10, 2021 at 15:13 Comment(1)
Excellent! I wonder why this answer doesn't have tons of upvotes!Chauncey

© 2022 - 2024 — McMap. All rights reserved.