0

I'm trying to create a toc.ncx (just an XML) file for an epub.

In such a toc, <navpoint>s are defined, each one having an id and a "playorder".

Is there any way for a Go template to simply count the navpoints?

I thought about something like this (non-working template code)

{{$counter := 0}}
{{define "NAVPOINT"}}
  {{$counter = $counter + 1}}
  <navpoint id="{{.}}" playorder="{{$counter}}">
{{end}}

{{range .TopLevel }}
  {{template "NAVPOINT" .Id}}
  {{range .SecondLevel }}
    {{template "NAVPOINT" .Id}}
    </navpoint>
  {{end}}
  </navpoint>
{{end}}

Example Structure

  { TopLevel: [
      { 
        Id: "id-a"
        SecondLevel: [
          {
            Id: "scnd-a"
          }
          {
            Id: "scnd-b"
          }
        ]
      }
      { 
        Id: "id-b"
        SecondLevel: [
          {
            Id: "scnd-c"
          }
          {
            Id: "scnd-d"
          }
        ]
      }
    }

This would then give me something like this

  <navpoint id="id-a"      playorder="1">
     <navpoint id="scnd-a" playorder="2"></navpoint>
     <navpoint id="scnd-b" playorder="3"></navpoint>
  </navpoint>
  <navpoint id="id-b"      playorder="4">
     <navpoint id="scnd-c" playorder="5"></navpoint>
     <navpoint id="scnd-d" playorder="6"></navpoint>
  </navpoint>

I think I can use a template function, not a template to achieve this, but have no clue how to achieve this. Can a template function have a counter?

Skeeve
  • 7,188
  • 2
  • 16
  • 26
  • 2
    There is a counter example in this [answer](https://stackoverflow.com/questions/42662525/go-template-remove-the-last-comma-in-range-loop/42663928#42663928), does that answer your question? – icza Aug 23 '20 at 21:52
  • Thanks a lot. That was really helpful. – Skeeve Aug 24 '20 at 04:42

1 Answers1

0

Thanks to @icza I found the solution here: Go template remove the last comma in range loop

This ist the function that I use now:

"navpoint": func() func(...string) string {
    i := 0
    return func(id ...string) string {
        if len(id) < 1 {
            return "</navPoint>"
        }
        i++
        return `<navPoint id="` + id[0] + `" playorder"` + strconv.Itoa(i) + `">`
    }
},

And I use it this way in the template:

{{$navpoint := navpoint}}
{{range .TopLevel }}
  {{call $navpoint .Id}}
  {{range .SecondLevel }}
    {{call $navpoint .Id}}
    {{call $navpoint}}
  {{end}}
  {{call $navpoint}}
{{end}}

If "navpoint" is called with an id (XX) it gives the opening tag <navpoint id="XX" playorder="##">. When called without an id, it gives the closing tag </navpoint>

Skeeve
  • 7,188
  • 2
  • 16
  • 26