Golang自定义解组XML

I have been trying to write a custom Unmarshal to deal with some XML code.

I know that you can write a custom unmarshal method to deal with an individual field within a struct, however I was trying to write one on the whole struct:

type LowestPricedPricedOffers struct {
ASIN   string `xml:"GetLowestPricedOffersForASINResult>Identifier>ASIN"`
TimeOfOfferChange string  `xml:"GetLowestPricedOffersForASINResult>Identifier>TimeOfOfferChange"`
TotalOfferCount int   `xml:"GetLowestPricedOffersForASINResult>Summary>TotalOfferCount"`
ListPrice         float32 `xml:"GetLowestPricedOffersForASINResult>Summary>ListPrice>Amount"`
LowestNew         float32 //lowest new landed price
LowestUsed        float32 //lowest used landed price
OfferCount        map[string]map[string]int
CurrencyCode      string //currency code taken from LowestPrices
NumberOfOffers    []struct {
    OfferCount         string `xml:",innerxml"` //Will not work with int
    Condition          string `xml:"condition,attr"`
    FulfillmentChannel string `xml:"fulfillmentChannel,attr"`
} `xml:"GetLowestPricedOffersForASINResult>Summary>NumberOfOffers>OfferCount"`
LowestPrices []struct {
    Condition          string         `xml:"condition,attr"`
    FulfillmentChannel string         `xml:"fulfillmentChannel,attr"`
    LandedPrice        float32Unmarsh `xml:"LandedPrice>Amount"`
    ListingPrice       float32        `xml:"ListingPrice>Amount"`
    Shipping           float32        `xml:"Shipping>Amount"`
    CurrencyCode       string         `xml:"LandedPrice>CurrencyCode"`
} `xml:"GetLowestPricedOffersForASINResult>Summary>LowestPrices>LowestPrice"`
}


func (n *LowestPricedPricedOffers) UnmarshalXML(d *xml.Decoder, start    xml.StartElement) error {
for {
    t, err := d.Token()
    if err == io.EOF {
        break
    }

    switch tt := t.(type) {
    case xml.StartElement:
        var value int
        if tt.Name.Local == "OfferCount" {
            d.DecodeElement(&value, &start)
            var condition string
            var fullfillmentChannel string
            for _, x := range tt.Attr {
                //fmt.Println(x.Name.Local, x.Value)
                if x.Name.Local == "condition" {
                    condition = x.Value
                    fmt.Println(condition)

                } else {
                    fullfillmentChannel = x.Value
                }

            }
            if n.OfferCount == nil {
                n.OfferCount = make(map[string]map[string]int)
                n.OfferCount[condition] = make(map[string]int)
                n.OfferCount[condition][fullfillmentChannel] = value

            } else {
                if n.OfferCount[condition] == nil {
                    n.OfferCount[condition] = make(map[string]int)
                }
                n.OfferCount[condition][fullfillmentChannel] = value
            }

        } else if tt.Name.Local == "ASIN" {
            d.DecodeElement(&n.ASIN, &start)
        }

        // More else if's to deal with rest of XML

    }
}
return nil
}

This seems to work in that I can control how my struct is populated, e.g in generating the map for 'OfferCount'. With my generalized approach, I then need to manually populate the rest of the struct using e.g

} else if tt.Name.Local == "ASIN" {
        d.DecodeElement(&n.ASIN, &start)
    }

Which I would have to do for all the elements in the XML, having to specify the struct field for each element. Is there a way using my approach that I can override for certain elements but just auto-populate the rest utilizing the tags in the struct as per a standard unmarshal without generating individual types for struct fields?

I have posted the full code on the go playground :

I hope this makes some sense.

I have updated my approach and question, to use custom types and custom unmarshalling on them.

The main struct has been updated as follows:

type LowestPricedPricedOffers struct {

Error AmazonError `xml:"Error"`
All   struct {

        /*The only way I found to retrieve 'status' from the GetLowestPricedOffersForASINResult element was to wrap in the struct 'All'.
        This is the only reason the All struct exists.  Ideally would like to remove*/
        Status            string     `xml:"status,attr"` 

    ASIN              string     `xml:"Identifier>ASIN"`
    ItemCondition     string     `xml:"Identifier>ItemCondition"`
    TimeOfOfferChange string     `xml:"Identifier>TimeOfOfferChange"`
    TotalOfferCount   int        `xml:"Summary>TotalOfferCount"`
    ListPrice         float32    `xml:"Summary>ListPrice>Amount"`
    OfferCount        offerCount `xml:"Summary>NumberOfOffers"`

    //Want to take Currency code from LowestPrices below but cannot think of a way to achieve this against the lowestPrices type
    //CurrencyCode         string               `xml:"CurrencyCode"` 

    BuyBoxPrices         buyBoxPrices         `xml:"Summary>BuyBoxPrices"`
    LowestPrices         lowestPrices         `xml:"Summary>LowestPrices"`
    BuyBoxEligibleOffers buyBoxEligibleOffers `xml:"Summary>BuyBoxEligibleOffers"`

    Offers []struct {
        SubCondition                 string  `xml:"SubCondition"`
        SellerPositiveFeedbackRating float32 `xml:"SellerFeedbackRating>SellerPositiveFeedbackRating"`
        FeedbackCount                int     `xml:"SellerFeedbackRating>FeedbackCount"`
        ShippingTime                 struct {
            MinimumHours     int    `xml:"minimumHours,attr"`
            MaximumHours     int    `xml:"maximumHours,attr"`
            AvailabilityType string `xml:"availabilityType,attr"`
        }
        ListingPrice        float32 `xml:"ListingPrice>Amount"`
        Shipping            float32 `xml:"Shipping>Amount"`
        ShipsFrom           string  `xml:"ShipsFrom>Country"`
        IsFulfilledByAmazon bool    `xml:"IsFulfilledByAmazon"`
        IsBuyBoxWinner      bool    `xml:"IsBuyBoxWinner"`
        IsFeaturedMerchant  bool    `xml:"IsFeaturedMerchant"` //true if the seller of the item is eligible to win the Buy Box.
    } `xml:"Offers>Offer"`
} `xml:"GetLowestPricedOffersForASINResult"`

}

It includes the 'All' struct which seemed to be the only way to get the unmarshalling of 'status' from the GetLowestPricedOffersForASINResult element. Ideally I would like to get rid of this wrapper struct, but I am not sure that this is possible.

Some of the custom types are maps, to allow for easy retrieval of data:

type offerCount map[string]map[string]int

func (m *offerCount) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {

var content map[string]map[string]int
for {
    t, err := d.Token()
    if err == io.EOF {
        break
    }
    switch tt := t.(type) {
    case xml.StartElement:
        var value int
        if tt.Name.Local == "OfferCount" {
            d.DecodeElement(&value, &start)
            var condition string
            var fullfillmentChannel string
            for _, x := range tt.Attr {

                if x.Name.Local == "condition" {
                    condition = x.Value

                } else {
                    fullfillmentChannel = x.Value

                }

            }

            if content == nil {
                content = make(map[string]map[string]int)
                content[condition] = make(map[string]int)
                content[condition][fullfillmentChannel] = value

            } else {
                if content[condition] == nil {
                    content[condition] = make(map[string]int)
                }
                content[condition][fullfillmentChannel] = value
            }


        }
    }
    *m = offerCount(content)
}
return nil

}

I am also trying to work out how to set CurrencyCode via the lowestPrices type, not sure if that is possible?

The full updated code is on the go playground for general comment or advice.