解析动态XML

huangapple go评论91阅读模式
英文:

Unmarshal dynamic XML

问题

我一直在使用unmarshal而没有任何问题,直到我遇到一个XML标签名是动态的情况。

XML可能是这样的:

<unit_amount_in_cents>
 <USD type="integer">4000</USD>
</unit_amount_in_cents>
<setup_fee_in_cents>
 <USD type="integer">4000</USD>
</setup_fee_in_cents>

或者

 <unit_amount_in_cents>
  <GBP type="integer">4000</GBP>
 </unit_amount_in_cents>
 <setup_fee_in_cents>
  <GBP type="integer">4000</GBP>
 </setup_fee_in_cents>

或者可能同时存在(或更多)

<unit_amount_in_cents>
 <USD type="integer">4000</USD>
 <GBP type="integer">4000</GBP>
</unit_amount_in_cents>
<setup_fee_in_cents>
 <USD type="integer">4000</USD>
 <GBP type="integer">4000</USD>
</setup_fee_in_cents>

我可以通过将XML.Name.Local分配给我需要的值来成功地将其编组为XML,但无法解组。

这是结构体的样子

type Plan struct {
    XMLName xml.Name `xml:"plan"`
    Name string `xml:"name,omitempty"`
    PlanCode string `xml:"plan_code,omitempty"`
    Description string `xml:"description,omitempty"`
    SuccessUrl string `xml:"success_url,omitempty"`
    CancelUrl string `xml:"cancel_url,omitempty"`
    DisplayDonationAmounts bool `xml:"display_donation_amounts,omitempty"`
    DisplayQuantity bool `xml:"display_quantity,omitempty"`
    DisplayPhoneNumber bool `xml:"display_phone_number,omitempty"`
    BypassHostedConfirmation bool `xml:"bypass_hosted_confirmation,omitempty"`
    UnitName string `xml:"unit_name,omitempty"`
    PaymentPageTOSLink string `xml:"payment_page_tos_link,omitempty"`
    PlanIntervalLength int `xml:"plan_interval_length,omitempty"`
    PlanIntervalUnit string `xml:"plan_interval_unit,omitempty"`
    AccountingCode string `xml:"accounting_code,omitempty"`
    CreatedAt *time.Time `xml:"created_at,omitempty"`
    SetupFeeInCents CurrencyArray `xml:"setup_fee_in_cents,omitempty"`
    UnitAmountInCents CurrencyArray `xml:"unit_amount_in_cents,omitempty"`
}

type CurrencyArray struct {
    CurrencyList []Currency
}

func (c *CurrencyArray) AddCurrency(currency string, amount int) {
    newc := Currency{Amount:fmt.Sprintf("%v",amount)}
    newc.XMLName.Local = currency
    c.CurrencyList = append(c.CurrencyList, newc)
}

func (c *CurrencyArray) GetCurrencyValue(currency string) (value int, e error) {
    for _, v := range c.CurrencyList {
            if v.XMLName.Local == currency {
                    value, e = strconv.Atoi(v.Amount)
                    return
            } 
    }
    e = errors.New(fmt.Sprintf("%s not found",currency))
    return
}       
    
type Currency struct {
    XMLName xml.Name `xml:""`
    Amount string `xml:",chardata"`
}
英文:

I have been using unmarshal without any problems until I came across a situation where the XML tag name is dynamic.

XML Could look like:

<unit_amount_in_cents>
 <USD type="integer">4000</USD>
</unit_amount_in_cents>
<setup_fee_in_cents>
 <USD type="integer">4000</USD>
</setup_fee_in_cents>

or

 <unit_amount_in_cents>
  <GBP type="integer">4000</GBP>
 </unit_amount_in_cents>
 <setup_fee_in_cents>
  <GBP type="integer">4000</GBP>
 </setup_fee_in_cents>

or could have both (or more)

<unit_amount_in_cents>
 <USD type="integer">4000</USD>
 <GBP type="integer">4000</GBP>
</unit_amount_in_cents>
<setup_fee_in_cents>
 <USD type="integer">4000</USD>
 <GBP type="integer">4000</USD>
</setup_fee_in_cents>

I can marshal to xml w/o problems by assigning the XML.Name.Local to what I need it to be but can't unmarshal it.

Here is what the struct looks like

type Plan struct {
    XMLName xml.Name `xml:"plan"`
    Name string `xml:"name,omitempty"`
    PlanCode string `xml:"plan_code,omitempty"`
    Description string `xml:"description,omitempty"`
    SuccessUrl string `xml:"success_url,omitempty"`
    CancelUrl string `xml:"cancel_url,omitempty"`
    DisplayDonationAmounts bool `xml:"display_donation_amounts,omitempty"`
    DisplayQuantity bool `xml:"display_quantity,omitempty"`
    DisplayPhoneNumber bool `xml:"display_phone_number,omitempty"`
    BypassHostedConfirmation bool `xml:"bypass_hosted_confirmation,omitempty"`
    UnitName string `xml:"unit_name,omitempty"`
    PaymentPageTOSLink string `xml:"payment_page_tos_link,omitempty"`
    PlanIntervalLength int `xml:"plan_interval_length,omitempty"`
    PlanIntervalUnit string `xml:"plan_interval_unit,omitempty"`
    AccountingCode string `xml:"accounting_code,omitempty"`
    CreatedAt *time.Time `xml:"created_at,omitempty"`
    SetupFeeInCents CurrencyArray `xml:"setup_fee_in_cents,omitempty"`
    UnitAmountInCents CurrencyArray `xml:"unit_amount_in_cents,omitempty"`
}

type CurrencyArray struct {
    CurrencyList []Currency
}

func (c *CurrencyArray) AddCurrency(currency string, amount int) {
    newc := Currency{Amount:fmt.Sprintf("%v",amount)}
    newc.XMLName.Local = currency
    c.CurrencyList = append(c.CurrencyList, newc)
}

func (c *CurrencyArray) GetCurrencyValue(currency string) (value int, e error) {
    for _, v := range c.CurrencyList {
            if v.XMLName.Local == currency {
                    value, e = strconv.Atoi(v.Amount)
                    return
            } 
    }
    e = errors.New(fmt.Sprintf("%s not found",currency))
    return
}       
    
type Currency struct {
    XMLName xml.Name `xml:""`
    Amount string `xml:",chardata"`
}

答案1

得分: 7

你的CurrencyList字段上需要标签xml:",any"

英文:

You need the tag xml:",any" on your CurrencyList field.

http://play.golang.org/p/i23w03z6R4

huangapple
  • 本文由 发表于 2012年6月7日 05:04:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/10922269.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定