hackeryarn
hackeryarn

Reputation: 312

Unmarshal XML Into a Map

As the title states I am trying to unmarshal my XML directly into a map instead of having to first unmarshal into a struct and then convert the struct into a map. I am dealing a fairly large data set and the dual conversion is taking more time than desired.

If anyone could provide any guidance on this at all it would be greatly appreciated.

XML: The classAccesses repeat and there are a few other elements.

<classAccesses>
    <apexClass>AccountRelationUtility</apexClass>
    <enabled>true</enabled>
</classAccesses>

My current struct: I parse out each of the header elements first and then create a new struct with the child elemtnts

type classAccesses struct {
    ApexClass string `xml:"apexClass"`
    Enabled   string `xml:"enabled"`
}

type diffs struct {
    ClassAccesses []classAccesses `xml:"classAccesses"`
}

Desired map: I want to keep the diffs struct, but I want the child struct "ClassAccesses" to become similar to the below map.

map[string]string {
    "ApexClass": "enabled"
}

Upvotes: 2

Views: 10316

Answers (2)

Daniel Petersson
Daniel Petersson

Reputation: 31

If you create a type that implements the xml.Unmarshaller interface then you can marshal your data directly into a map[string]string.

type classAccessesMap struct {
    m map[string]string
}

func (c *classAccessesMap) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    c.m = map[string]string{}

    key := ""
    val := ""

    for {
        t, _ := d.Token()
        switch tt := t.(type) {

        // TODO: parse the inner structure

        case xml.StartElement:
            fmt.Println(">", tt)    

        case xml.EndElement:
            fmt.Println("<", tt)
            if tt.Name == start.Name {
                return nil
            }

            if tt.Name.Local == "enabled" {
                c.m[key] = val
            }
        }
    }
}

Here is a partial solution; https://play.golang.org/p/7aOQ5mcH6zQ

Upvotes: 3

Peter Stace
Peter Stace

Reputation: 1434

As of Go 1.3, it is not possible to unmarshal an XML document directly into a map using the standard Go library.

The XML part of the standard library is given here, http://golang.org/pkg/encoding/xml/, there are no functions to do exactly what you ask for in the question.

Depending on the specifics of your situation, you may have other options such as:

  • Parallelise your algorithm, i.e. read from the file and decode at the same time. This will only work well if you have multiple files to read from.
  • Write your own XML decoding algorithm in Go.

Upvotes: 2

Related Questions