#xml #go
#xml #Вперед
Вопрос:
У меня есть фрагмент 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>
Я создал здесь игровую площадку
Комментарии:
1. Ваша структура не представляет, как вы хотите, чтобы выглядел ваш вывод, и на самом деле это довольно сложно сделать таким образом. Вероятно, вам понадобится либо
[]interface{}
с чередующимисяCondition
иOperator
элементами, либо написать пользовательскийMarshalXML
метод для вашего типа.
Ответ №1:
Условия чередования и элементы оператора в массиве []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)
}