将数组封送到go中的单个xml元素

时间:2012-12-10 01:12:42

标签: xml go marshalling

我正在学习Go,编写一个以Collada格式生成文件的程序,该程序使用XML描述几何。

你注释你的结构,几乎所有的东西都按照你的预期工作,除了我无法弄清楚如何将数组编组成一个XML元素 - 我总是最终生成N个元素。

换句话说,我想

<input>
    <p>0 1 2</p>
</input> 

而不是

<input>
    <p>0</p>
    <p>1</p>
    <p>2</p>
</input> 

代码如下

package main

import (
    "encoding/xml"
    "os"
)

func main() {
    type Vert struct {
        XMLName xml.Name    `xml:"input"`
        Indices     []int   `xml:"p"`
    }

    v := &Vert{Indices:[]int{0, 1, 2}}
    output, err := xml.MarshalIndent(v, "", "    ")
    if err == nil {
        os.Stdout.Write(output)
    }
}

来自encoding/xml/marshal.go的各种评论(和代码)似乎暗示我运气不好:

  

// Marshal通过编组每个元素来处理数组或切片   //切片和数组迭代元素。它们没有封闭标签。

奇怪的是,如果我将我的数组类型更改为uint8,则根本不会对数组进行编组。

如果我运气不好,我可能会使用xml:“,innerxml”注释自己替换数组。

2 个答案:

答案 0 :(得分:1)

正如您所猜测的,encoding / xml将无法开箱即用。你可以这样做:

import (
    "strconv"
    "strings"
)

type Vert struct {
    P string `xml:"p"`
}

func (v *Vert) SetIndices(indices []int) {
    s := make([]string, len(indices))
    for i := range indices {
        s[i] = strconv.FormatInt(int64(indices[i]), 10)
    }
    v.P = strings.Join(s, " ")
}

编辑:我最初写了一个getter而不是setter。

答案 1 :(得分:0)

最后我为这种类型的数组做了我自己的xml编组, 将类型更改为string并使用innerxml属性。

package main

import (
    "encoding/xml"
    "os"
    "fmt"
    "bytes"
)

func MyMarshalArray(indices []int) string {
    var buffer bytes.Buffer

    buffer.WriteString("<p>")
    for i := 0; i < len(indices); i++ {
        buffer.WriteString(fmt.Sprintf("%v ", indices[i]))
    }
    buffer.WriteString("</p>")
    return buffer.String()
}

func main() {
    type Vert struct {
        XMLName xml.Name    `xml:"input"`
        Indices     string  `xml:",innerxml"`
    }

    v := &Vert{Indices:MyMarshalArray([]int{0, 1, 2})}
    output, err := xml.MarshalIndent(v, "", "    ")
    if err == nil {
        os.Stdout.Write(output)
    }
}