在Go中如何将任意的XML属性编组到一个元素中?

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

Marshal arbitrary XML attributes in an element in Go?

问题

我需要在运行时在元素上编组额外的属性。我尝试了以下代码:

type Meh struct {
    XMLName xml.Name
    Attrs []xml.Attr
}

Meh{
    Attrs: []xml.Attr{
        xml.Attr{xml.Name{Local: "hi"}, "there"},
    },  
}

但是这些字段被视为新的元素:

<Meh><Attrs><Name></Name><Value>there</Value></Attrs></Meh>

如果我在Attr字段上添加标签xml:",attr",它会期望一个[]bytestring来指定单个属性的内容。

如何在运行时指定属性?如何注释类型以提供字段来实现这一点?

英文:

I need to marshal in extra attributes on an element at runtime. I've tried this:

type Meh struct {
    XMLName xml.Name
    Attrs []xml.Attr
}

Meh{
    Attrs: []xml.Attr{
        xml.Attr{xml.Name{Local: &quot;hi&quot;}, &quot;there&quot;},
    },  
}

But the fields are treated as new elements:

&lt;Meh&gt;&lt;Attrs&gt;&lt;Name&gt;&lt;/Name&gt;&lt;Value&gt;there&lt;/Value&gt;&lt;/Attrs&gt;&lt;/Meh&gt;

If I add the tag xml:&quot;,attr&quot; to the Attr field, it expects a []byte or string specifying the contents of a single attribute.

How do I specify attributes at runtime? How do I annotate the type to provide field(s) for this?

答案1

得分: 2

你可以尝试直接使用模板。示例:

package main

import (
    "bytes"
    "encoding/xml"
    "fmt"
    "text/template"
)

type ele struct {
    Name  string
    Attrs []attr
}

type attr struct {
    Name, Value string
}

var x = `<{{.Name}}{{range $a := .Attrs}} {{$a.Name}}="{{xml $a.Value}}"{{end}}>`

func main() {
    // 在这里定义了模板函数 "xml",用于基本转义,处理特殊字符如 "。
    t := template.New("").Funcs(template.FuncMap{"xml": func(s string) string {
        var b bytes.Buffer
        xml.Escape(&b, []byte(s))
        return b.String()
    }})
    template.Must(t.Parse(x))
    e := ele{
        Name: "Meh",
        Attrs: []attr{
            {"hi", "there"},
            {"um", `I said "hello?"`},
        },
    }
    b := new(bytes.Buffer)
    err := t.Execute(b, e)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(b)
}

输出:

<Meh hi="there" um="I said &#34;hello?&#34;">
</Meh>
英文:

You might try working directly with templates. Example:

package main

import (
    &quot;bytes&quot;
    &quot;encoding/xml&quot;
    &quot;fmt&quot;
    &quot;text/template&quot;
)

type ele struct {
    Name  string
    Attrs []attr
}

type attr struct {
    Name, Value string
}

var x = `&lt;{{.Name}}{{range $a := .Attrs}} {{$a.Name}}=&quot;{{xml $a.Value}}&quot;{{end}}&gt;
&lt;/{{.Name}}&gt;`

func main() {
    // template function &quot;xml&quot; defined here does basic escaping,
    // important for handling special characters such as &quot;.
    t := template.New(&quot;&quot;).Funcs(template.FuncMap{&quot;xml&quot;: func(s string) string {
        var b bytes.Buffer
        xml.Escape(&amp;b, []byte(s))
        return b.String()
    }})
    template.Must(t.Parse(x))
    e := ele{
        Name: &quot;Meh&quot;,
        Attrs: []attr{
            {&quot;hi&quot;, &quot;there&quot;},
            {&quot;um&quot;, `I said &quot;hello?&quot;`},
        },
    }
    b := new(bytes.Buffer)
    err := t.Execute(b, e)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(b)
}

Output:

&lt;Meh hi=&quot;there&quot; um=&quot;I said &amp;#34;hello?&amp;#34;&quot;&gt;
&lt;/Meh&gt;

huangapple
  • 本文由 发表于 2012年5月31日 14:00:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/10828187.html
匿名

发表评论

匿名网友

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

确定