Problem
I need to unmarshal XML
from an 3rd party application to my GO struct.
what i tried
I created structs and am able to generate identical XML
from my code.
@see TestMetaData_Marshal
ValidXML
i simplified the xml for this example:
<Parent>
<Name>tic.TEST</Name>
<MetaData>
<LawFormID Type="129" DefinedSize="3">DOO</LawFormID>
<FirmUQ Type="129" DefinedSize="15">BARTOG</FirmUQ>
<FirmDescription Type="200" DefinedSize="100">Bartog d.o.o. Trebnje</FirmDescription>
</MetaData>
</Parent>
Structs
my corresponding structs are the following. NOTE: i created a struct for MetaData though i would prefer to NOT use one (due json, yaml)
type Parent struct {
Name string
MetaData []Node `xml:"MetaData>any"`
}
type Node struct {
XMLName xml.Name // this allows custom node names
Type int `xml:"Type,attr,omitempty"`
DefinedSize int `xml:"DefinedSize,attr,omitempty"`
Text string `xml:",chardata"` // required at some places, cannot omit
}
@TestMetadata_Marshal
func TestMetaData_Marshal(t *testing.T) {
parent := Parent{
Name: "tic.TEST",
MetaData: []Node{
{
XMLName: xml.Name{
Local: "LawFormID",
},
Text: "DOO",
Type: 129,
DefinedSize: 3,
}, {
XMLName: xml.Name{
Local: "FirmUQ",
},
Text: "BARTOG",
Type: 129,
DefinedSize: 15,
}, {
XMLName: xml.Name{
Local: "FirmDescription",
},
Text: "Bartog d.o.o. Trebnje",
Type: 200,
DefinedSize: 100,
},
}, // \MetaData
}
HaveXML := XML(parent)
fmt.Println(HaveXML)
if ValidXML != HaveXML {
t.Error(fmt.Errorf("marshaled XML did not match. Have: %v", HaveXML))
}
}
Unmarshal
this is where the troubles begin; the test func
is trivial; result is that no entries in MetaData
are available.
I tried a lot of different tag
s, also tried creating an own MetaData
struct
containing Items []Node
func TestUnmarshal() {
var parent Parent
err := xml.Unmarshal([]byte(ValidXML), &parent)
if err != nil {
fmt.Println(err)
return
}
HaveXML := XML(parent)
if ValidXML == HaveXML {
fmt.Println("\tmarshaled XML is Valid")
} else {
fmt.Printf("\tmarshaled XML did not match. Have:\n%v\n", HaveXML)
}
}
go play (turned tests into 'normal' funcs
https://goplay.tools/snippet/kWS29HR7O9t
Question
Is it not possible to do this in go&xml? Iff it IS possible, what am i doing wrong?
CodePudding user response:
The problem is that any
is not the tag name, it's an option. So when using it, you have to put a comma before it, e.g. xml:",any"
.
I don't think you can combine it with >
, so create a separate MetaData
struct:
type Parent struct {
Name string
MetaData MetaData `xml:"MetaData"`
}
type MetaData struct {
Nodes []Node `xml:",any"`
}
With this refactoring your example works and outputs (try it on the Go Playground):
=== TestMarshal
<Parent>
<Name>tic.TEST</Name>
<MetaData>
<LawFormID Type="129" DefinedSize="3">DOO</LawFormID>
<FirmUQ Type="129" DefinedSize="15">BARTOG</FirmUQ>
<FirmDescription Type="200" DefinedSize="100">Bartog d.o.o. Trebnje</FirmDescription>
</MetaData>
</Parent>
marshaled XML is Valid
=== TestUnmarshal
marshaled XML is Valid