自定义XML Marshal用于其间包含字符串的数组

问题描述 投票:-1回答:1

我有一段需要读写的XML代码。这是一个<condition>阵列,除了最后一个实体之外,每个都有<operator>

<conditions>                                                                                                                                                                                                                                                                              
    <condition>                                                                                                                                                                                                                                                                           
      <label>a</label>                                                                                                                                                                                                                                                                    
    </condition>                                                                                                                                                                                                                                                                          
    <operator>AND</operator>                                                                                                                                                                                                                                                              
    <condition>                                                                                                                                                                                                                                                                           
      <label>b</label>                                                                                                                                                                                                                                                                    
    </condition>                                                                                                                                                                                                                                                                          
    <operator>AND</operator>                                                                                                                                                                                                                                                              
    <condition>                                                                                                                                                                                                                                                                           
      <label>c</label>                                                                                                                                                                                                                                                                    
    </condition>                                                                                                                                                                                                                                                                          
<conditions>

我的Go模型看起来像这样

type Condition struct {                                                                                                                                                                                                                                                                   
    XMLName xml.Name `xml:"condition" json:"-"`                                                                                                                                                                                                                                           
    Label   string   `xml:"label"`                                                                                                                                                                                                                                                        
}                                                                                                                                                                                                                                                                                         

type Conditions struct {                                                                                                                                                                                                                                                                  
    ConditionList []Condition `xml:"condition,omitempty"`                                                                                                                                                                                                                                 
    Operator      string      `xml:"operator"`                                                                                                                                                                                                                                            
}   

如果我编组结构,则操作符只在底部出现一次。正如所料

<Conditions>
  <condition>
    <label>a</label>
  </condition>
  <condition>
    <label>b</label>
  </condition>
  <condition>
    <label>c</label>
  </condition>
  <operator>AND</operator>
</Conditions>

除了最后一个条件之外,我如何让操作员出现在每个条件之后?

我能得到的最接近的是使用包装器

func (c Conditions) MarshalXML(e *xml.Encoder, start xml.StartElement) error {                                                                                                                                                                                                            

    type tCondition struct {                                                                                                                                                                                                                                                              
        XMLName xml.Name `xml:"condition" json:"-"`                                                                                                                                                                                                                                       
        Label   string   `xml:"label"`                                                                                                                                                                                                                                                    
    }                                                                                                                                                                                                                                                                                     
    type tConditionWithOp struct {                                                                                                                                                                                                                                                        
        XMLName   xml.Name   `xml:"-" json:"-"`                                                                                                                                                                                                                                           
        Condition tCondition `xml: "conditions"`                                                                                                                                                                                                                                          
        Operator  string     `xml:",omitempty"`                                                                                                                                                                                                                                           
    }                                                                                                                                                                                                                                                                                     
    type tWrapper struct {                                                                                                                                                                                                                                                                
        OPS []tConditionWithOp                                                                                                                                                                                                                                                            
    }                                                                                                                                                                                                                                                                                     

    lst := make([]tConditionWithOp, 0, 10)                                                                                                                                                                                                                                                

    for idx, cond := range c.ConditionList {                                                                                                                                                                                                                                              
        tCond := tCondition{                                                                                                                                                                                                                                                              
            Label: cond.Label,                                                                                                                                                                                                                                                            
        }                                                                                                                                                                                                                                                                                 
        tCondOp := tConditionWithOp{                                                                                                                                                                                                                                                      
            Condition: tCond,                                                                                                                                                                                                                                                             
        }                                                                                                                                                                                                                                                                                 

        if idx < len(c.ConditionList)-1 {                                                                                                                                                                                                                                                 
            tCondOp.Operator = c.Operator                                                                                                                                                                                                                                                 
        }                                                                                                                                                                                                                                                                                 

        lst = append(lst, tCondOp)                                                                                                                                                                                                                                                        

    }                                                                                                                                                                                                                                                                                     
    wrapper := tWrapper{                                                                                                                                                                                                                                                                  
        OPS: lst,                                                                                                                                                                                                                                                                         
    }                                                                                                                                                                                                                                                                                     

    return e.EncodeElement(wrapper, start)                                                                                                                                                                                                                                                
}  

但我现在有一个<OPS>标签

<Conditions>
  <OPS>
    <condition>
      <label>a</label>
    </condition>
    <Operator>AND</Operator>
  </OPS>
  <OPS>
    <condition>
      <label>b</label>
    </condition>
    <Operator>AND</Operator>
  </OPS>
  <OPS>
    <condition>
      <label>c</label>
    </condition>
  </OPS>
</Conditions>

我在这里创建了一个游乐场

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

xml go
1个回答
0
投票

将交叉条件和运算符元素放入[] interface {}数组中。谢谢

type Operator struct {                                                                                                                                       
    Name string                                                                                                                                              
}                                                                                                                                                            

func (op Operator) MarshalXML(e *xml.Encoder, start xml.StartElement) error {                                                                                
    start.Name.Local = "operator"                                                                                                                            
    return e.EncodeElement(op.Name, start)                                                                                                                   
}                                                                                                                                                            

func (c Conditions) MarshalXML(e *xml.Encoder, start xml.StartElement) error {                                                                               

    start.Name.Local = "conditions"                                                                                                                          
    var arr []interface{}                                                                                                                                    

    for idx, cond := range c.ConditionList {                                                                                                                 
        if idx > 0 {                                                                                                                                         
            arr = append(arr, Operator{Name: c.Operator})                                                                                                    
        }                                                                                                                                                    
        arr = append(arr, cond)                                                                                                                              
    }                                                                                                                                                        

    type root struct {                                                                                                                                       
        ARR []interface{}                                                                                                                                    
    }                                                                                                                                                        

    return e.EncodeElement(root{ARR: arr}, start)                                                                                                            
}
© www.soinside.com 2019 - 2024. All rights reserved.