LoginSignup
1
0

More than 1 year has passed since last update.

Goでtemplateを使って、xmlを生成してみる

Posted at

この記事はWanoグループ Advent Calendar 2021 4日目の記事になります

goのTemplateはtext/html二種類がある

しかしxml生成の際に、どっちでもそのまま使ってはいけません

例えば:

text/templateの場合

package main

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

type XmlTemplateMeta struct {
    Text string
}

func main() {

    var xmlTemplateStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<test>\n  <text>{{ .Text }}</text>\n</test>\n"

    // & 入れたら。。。
    x := XmlTemplateMeta{
        Text: "test string1 & string2",
    }

    tmpl := template.Must(template.New("xml_template").Parse(xmlTemplateStr))
    resBuffer := new(bytes.Buffer)

    tmpl.Execute(resBuffer, x)
    fmt.Printf("%v",resBuffer.String())

}

結果は:

<?xml version="1.0" encoding="UTF-8"?>
<test>
  <text>test string1 & string2</text>
</test>

&はescapeできなかった
もしhtml/templateを使う場合:

&lt;?xml version="1.0" encoding="UTF-8"?>
<test>
  <text>test string1 &amp; string2</text>
</test>

中身は出来ましたけど、先頭の<?xml 部分もescapeしようとしてしまう、これもダメですね

そうしたらhtml.EscapeStringを使って、中身は先に一回escapeの手もありますけど

package main

import (
    "bytes"
    "fmt"
    "html"
    "text/template"
)

type XmlTemplateMeta struct {
    Text string
}

func main() {

    var xmlTemplateStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<test>\n  <text>{{ .Text }}</text>\n</test>\n"

    x := XmlTemplateMeta{
        Text: html.EscapeString("test string1 & string2"),  // EscapeStringを使用
    }

    tmpl := template.Must(template.New("xml_template").Parse(xmlTemplateStr))
    resBuffer := new(bytes.Buffer)

    tmpl.Execute(resBuffer, x)
    fmt.Printf("%v",resBuffer.String())

}

結果:


<?xml version="1.0" encoding="UTF-8"?>
<test>
  <text>test string1 &amp; string2</text>
</test>


但しstructの構造体に対して、中のstringを再帰的に処理がいるので、結構面倒いですね。
そこでtempalteのpipeline機能を使ってやてみます


package main

import (
    "bytes"
    "fmt"
    "html"
    "text/template"
)

type XmlTemplateMeta struct {
    Text string
}

func main() {

    // tempalteの中もescapeの使用をお忘れなく
    var xmlTemplateStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<test>\n  <text>{{escape .Text }}</text>\n</test>\n"

    funcMap := map[string]interface{}{
        "escape": func(str string) string {
            return html.EscapeString(str)
        },
    }

    x := XmlTemplateMeta{
        Text: "test string1 & string2",
    }

    // funcMapの使用
    tmpl := template.Must(template.New("xml_template").Funcs(funcMap).Parse(xmlTemplateStr))
    resBuffer := new(bytes.Buffer)

    tmpl.Execute(resBuffer, x)
    fmt.Printf("%v",resBuffer.String())

}

これならescape設定は全部templateの中で完結するので、structの方気にしなくで良いですね

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0