2016-11-14 5 views
1

私はどういうわけか、私の{{ .blahblah }}アクションをテンプレートで文字列のスライスとして定義したいと思います。私は[]string{"name", "age"}を取得できるようにしたいと思いGolang、パースされたテンプレートからテンプレート「アクション」のマップやリストを取得する方法は?

<h1>{{ .name }} {{ .age }}</h1> 

:たとえば

私は、このテンプレートを持っている場合。

t := template.New("cooltemplate").Parse(`<h1>{{ .name }} {{ .age }}</h1>`) 
if t.Fields() == []string{"name", "age"} { 
    fmt.Println("Yay, now I know what fields I can pass in!") 
    // Now lets pass in the name field that we just discovered. 
    _ = t.Execute(os.Stdout, map[string]string{"name": "Jack", "age":"120"}) 
} 

このような解析されたテンプレートを検査する方法はあります:テンプレートメソッドfunc (t *Template) Fields() []stringを持っていることをふり?
ありがとうございます!

+0

テンプレートは、原料のこの種(FieldNode)を公開parse.Treeが含まれています。 docs: "* parse.Treeフィールドは、html/templateでのみ使用するためにエクスポートされ、他のすべてのクライアントからは認識されないように扱われなければなりません。 So:それをしないでください。あなたがそのアドバイスに従わなければ:幸運。 – Volker

答えて

0

はじめに:Vokerが示唆しているように、Template.Treeフィールドは「」であり、「html/templateでのみ使用するためにエクスポートされており、他のすべてのクライアントからは認識されないように扱われるべきです。

テンプレート実行の入力を提供するには、このようなことに頼るべきではありません。必要なデータとともに実行したいテンプレートを知っている必要があります。実行時に引数を提供するためにそれを "探索"するべきではありません。


テンプレートを解析から抜け出す値が(text/templateまたはhtml/templateのいずれか、彼らは同じAPIを持つ)template.Templateです。このテンプレートは、テンプレートをタイプparse.Treeのツリーとして表します。テキストテンプレートに含まれるすべてのものが、静的テキスト、アクションなどを含むノード内のこのツリーに格納されます。

このことから、このツリーを歩いて、フィールドまたはコール関数にアクセスするアクションを識別するノードを探すことができます。ノードはタイプがNode.Type()であるタイプparse.Nodeです。可能なタイプは、parseパッケージのparse.NodeTypeタイプの横の定数として定義されます。だからここ

const (
     NodeText NodeType = iota // Plain text. 
     NodeAction     // A non-control action such as a field evaluation. 
     NodeBool     // A boolean constant. 
     NodeChain     // A sequence of field accesses. 
     NodeCommand     // An element of a pipeline. 
     NodeDot      // The cursor, dot. 

     NodeField  // A field or method name. 
     NodeIdentifier // An identifier; always a function name. 
     NodeIf   // An if action. 
     NodeList  // A list of Nodes. 
     NodeNil  // An untyped nil constant. 
     NodeNumber  // A numerical constant. 
     NodePipe  // A pipeline of commands. 
     NodeRange  // A range action. 
     NodeString  // A string constant. 
     NodeTemplate // A template invocation action. 
     NodeVariable // A $ variable. 
     NodeWith  // A with action. 
) 

は、再帰的にテンプレートツリーを歩くプログラム例であり、あるNodeActionタイプ、とのノードを探します「などのフィールド評価などの非制御動作。」

このソリューションは単なるデモであり、概念の証明であり、すべてのケースを処理するわけではありません。

func ListTemplFields(t *template.Template) []string { 
    return listNodeFields(t.Tree.Root, nil) 
} 

func listNodeFields(node parse.Node, res []string) []string { 
    if node.Type() == parse.NodeAction { 
     res = append(res, node.String()) 
    } 

    if ln, ok := node.(*parse.ListNode); ok { 
     for _, n := range ln.Nodes { 
      res = listNodeFields(n, res) 
     } 
    } 
    return res 
} 

それを使用した例:

t := template.Must(template.New("cooltemplate"). 
    Parse(`<h1>{{ .name }} {{ .age }}</h1>`)) 
fmt.Println(ListTemplFields(t)) 

出力(Go Playground上でそれを試してみてください):

[{{.name}} {{.age}}] 
+0

あなたの答えをありがとう。明確にするために、実行時にアクションを取得する理由は、テンプレートの作成を制御できない場合や、テンプレートが頻繁に変更される場合です。たとえば、文字を表すテンプレートがあります。私は、ユーザーがテンプレートの値を入力できるGUIを持っています。明らかに、すべてのテンプレートには、いくつかの類似したアクションといくつかの異なるアクションが必要です。したがって、GUIは、実行時にテンプレート上に見つかったすべてのアクションの入力ボックスを表示できる必要があります。そうしないと、すべての単一テンプレートのすべての入力ボックスに静的にコードを記述する必要があります。 – JackMordaunt

関連する問題