如何使用Go to struct list格式化该xml?这个xml标签名称相同,只是id不同

I had a xml code, I want to format xml to struct list. I try to use “encoding/xml”, but the api not support filter by ID inside the tag. I want to format unionBankNo and bankName, but error. Please tell me there is a better solution?

this is my xml

<?xml version="1.0" encoding="utf-8"?>

<kColl id="noSessionSrvData" append="false"> 
  <field id="EMPException"/>  
  <field id="errorMessage"/>  
  <field id="customerId"/>  
  <field id="provinceCode"/>  
  <field id="provinceName"/>  
  <field id="cityCode" value="1000"/>  
  <field id="bankName"/>  
  <field id="bankType" value="104"/>  
  <field id="configName"/>  
  <field id="electricNo"/>  
  <field id="orderFlowNo"/>  
  <field id="dateTime"/>  
  <iColl id="iCityInfo" append="false"></iColl>  
  <iColl id="iBankInfo" append="false"> 
    <kColl id="null" append="false"> 
      <field id="unionBankNo" value="104100006610"/>  
      <field id="bankName" value="中国银行股份有限公司北京百子湾支行"/> 
    </kColl>  
    <kColl id="null" append="false"> 
      <field id="unionBankNo" value="104100004013"/>  
      <field id="bankName" value="中国银行股份有限公司北京市分行"/> 
    </kColl>  
    <kColl id="null" append="false"> 
      <field id="unionBankNo" value="104100004048"/>  
      <field id="bankName" value="中国银行股份有限公司北京崇文门支行"/> 
    </kColl>  
  </iColl>  
  <iColl id="iPayUseList" append="false"></iColl>  
  <iColl id="iBankNotice" append="false"></iColl>  
  <iColl id="iOrderList" append="false"></iColl>  
  <field id="activateCode"/>  
  <field id="payAccountOpenNode"/>  
  <iColl id="iCityBank" append="false"></iColl>  
  <field id="transferTowardType"/>  
  <field id="errorCode"/>  
  <field id="chargeFee"/>  
  <field id="userAlias"/>  
  <field id="password"/>  
  <field id="passwordEncrypted"/>  
  <field id="oldPassword"/>  
  <field id="passwordOld"/>  
  <field id="passwordNew"/>  
  <field id="userid"/>  
  <field id="flowId"/>  
  <field id="uifAlias"/>  
  <field id="stt"/>  
  <field id="queryNumber"/>  
  <field id="flagNo"/>  
  <field id="userId"/>  
  <field id="openDate"/>  
  <field id="turnPageBeginPos" value="1"/>  
  <field id="turnPageShowNum" value="10"/>  
  <field id="turnPageTotalNum"/>  
  <field id="queryType"/>  
  <field id="PBA_ID"/>  
  <field id="PBA_TYPE "/>  
  <field id="PBA_TITLE "/>  
  <field id="PBA_CONTENT "/>  
  <field id="PBA_TELLERNO "/>  
  <field id="PBA_DATETIME "/>  
  <field id="PBA_ACTIVEDATE "/>  
  <field id="PBA_EXPIREDATE "/>  
  <field id="PBA_STT "/>  
  <iColl id="iANNOUNCE" append="false"></iColl>  
  <iColl id="iUnionBankList" append="false"></iColl>  
  <field id="abateDate"/>  
  <field id="Dueday"/>  
  <field id="_ServletRequest" value=""/>  
  <field id="retValue" value="0"/> 
</kColl>

this is my struct

type UnionInfo struct {
    UnionNo string `xml:"field>[@id='unionBankNo']>id,attr"`
    BankName string `xml:"field>[@id='bankName']>id,attr"`
}

type Result struct {
    XMLName xml.Name `xml:"kColl"`
    Name    string
    City   string    `xml:"field>[@id='cityCode']>value,attr"`
    Province string
    UnionInfo []UnionInfo `xml:"iColl/kColl"`
}
err = xml.Unmarshal([]byte(body), &v)
    if err != nil {
        fmt.Printf("error: %v", err)
        return
    }

    fmt.Println(string(body))
    fmt.Println(v)

error: xml: field>[@id='cityCode']>value chain not valid with attr flagExiting.

With encoding/xml you can first parse the xml into the correct structure and then after that filter the necessary stuff yourself. Whether there's a 3rd party package that makes this simpler I don't know...

type KColl struct {
    Id     string  `xml:"id,attr"`
    Append bool    `xml:"append,attr"`
    Fields []Field `xml:"field"`
    IColls []IColl `xml:"iColl"`
}

type IColl struct {
    Id     string  `xml:"id,attr"`
    Append bool    `xml:"append,attr"`
    KColls []KColl `xml:"kColl"`
}

type Field struct {
    Id    string `xml:"id,attr"`
    Value string `xml:"value,attr"`
}

func main() {
    var k KColl
    if err := xml.Unmarshal(data, &k); err != nil {
        panic(err)
    }

    var res Result
    for _, f := range k.Fields {
        if f.Id != "cityCode" {
            continue
        }
        res.City = f.Value
        break
    }
    for _, i := range k.IColls {
        if i.Id != "iBankInfo" {
            continue
        }

        for _, j := range i.KColls {
            var info UnionInfo
            for _, f := range j.Fields {
                if f.Id == "unionBankNo" {
                    info.UnionNo = f.Value
                }
                if f.Id == "bankName" {
                    info.BankName = f.Value
                }
            }
            res.UnionInfo = append(res.UnionInfo, info)

        }
    }
    fmt.Printf("%+v
", res)
}

https://play.golang.org/p/W4LnMLKVa8z