1

Im not sure this is valid xml, unfortunately its what I'm having to deal with - looking for suggestions on how to accomplish.

my xml looks like this:

<report>
    <sort>
        <field>type<order>ascending</order></field>
    </sort>
</report>

I am attempting to unmarshall into the following structs:

type Sort struct {
    Field string `xml:"field"`
    Order string `xml:"field>order"`
}

type Report struct {
    Sort Sort       `xml:"sort"`
}

unfortunately this is throwing the error:

Unmarshalling error: v7.Sort field "Field" with tag "field" conflicts with field "Order" with tag "field>order"

Is there a built in way of achieving this or am I looking at some custom unmarshalling

UPDATE: At least according to this answer it appears this should be valid if slightly ugly xml: Can a XML element contain text and child elements at the same time?

SwiftD
  • 5,769
  • 6
  • 43
  • 67
  • It's definitely not valid XML, `` is not terminated and just plain invalid. Don't try to parse it as xml. – Marc Feb 14 '18 at 17:13
  • sorry corrected xml sample, field field is terminated (typo) - but i think still invalid as data and node inside node – SwiftD Feb 14 '18 at 17:14
  • Looks valid, it's just that order is not a direct sibling of field but of a text node. – LMC Feb 14 '18 at 17:25

1 Answers1

1

A single XML element can only be mapped to a single struct field, and your model tries to map <field> to 2 struct fields, so it's not allowed.

The character data of <field> and the child element <order> are at the same "level", they are siblings, so they must be in the same struct. But they are different types of nodes: to get the character data, use the xml:",chardata" struct tag, and to get the value of the <order> child element, use the xml:"order" struct tag.

So use the following Go model:

type Field struct {
    Value string `xml:",chardata"`
    Order string `xml:"order"`
}

type Sort struct {
    Field Field `xml:"field"`
}

type Report struct {
    Sort Sort `xml:"sort"`
}

Parsing your input XML into this model:

func main() {
    var r Report
    err := xml.Unmarshal([]byte(src), &r)
    fmt.Printf("%+v %v", r, err)
}

const src = `<report>
    <sort>
        <field>type<order>ascending</order></field>
    </sort>
</report>`

Output is (try it on the Go Playground):

{Sort:{Field:{Value:type Order:ascending}}} <nil>

Since Sort only contains a single Field field, we can simplify the model to this:

type Field struct {
    Value string `xml:",chardata"`
    Order string `xml:"order"`
}

type Report struct {
    SortField Field `xml:"sort>field"`
}

And it works the same way, gives a similar output (try this one on the Go Playground):

{SortField:{Value:type Order:ascending}} <nil>
icza
  • 389,944
  • 63
  • 907
  • 827