Files
lenz-web/xmlparsing/token.go
Simon Martens 9563145aeb Lots of stuff
2025-06-24 18:20:06 +02:00

127 lines
2.0 KiB
Go

package xmlparsing
import (
"encoding/xml"
"iter"
"strings"
)
type TokenType int
const (
StartElement TokenType = iota
EndElement
CharData
Comment
ProcInst
Directive
)
type Token struct {
Name string
Attributes map[string]string
Inner xml.Token
Type TokenType
Data string
Stack []*Token
StartOffset int64
EndOffset int64
Index int
charData string
children []*Token
parser *Parser
childrenParsed bool
chardataParsed bool
}
func (t *Token) String() string {
builder := strings.Builder{}
return builder.String()
}
func (t *Token) Element() (tokens []*Token) {
if t.Type != StartElement {
return
}
for token, err := range t.parser.PeekFrom(t.Index) {
if err != nil || token == nil {
return tokens
}
tokens = append(tokens, token)
if token.Type == EndElement && token.Name == t.Name {
return tokens
}
}
return
}
func (t *Token) Next() iter.Seq2[*Token, error] {
return t.parser.PeekFrom(t.Index)
}
func (t *Token) Previous() (tokens []*Token) {
if t.Index <= 0 {
return
}
return t.parser.Previous(t.Index)
}
func (t *Token) Children() (tokens []*Token) {
if t.childrenParsed {
return t.children
}
tokens = t.Element()
if len(tokens) == 0 {
return
}
for _, token := range tokens {
if token.Type == StartElement {
t.children = append(t.children, token)
}
}
t.childrenParsed = true
return t.children
}
func (t *Token) CharData() string {
if t.Type == CharData || t.Type == ProcInst || t.Type == Comment || t.Type == Directive {
return t.Data
}
if t.chardataParsed {
return t.charData
}
tokens := t.Element()
if len(tokens) == 0 {
return ""
}
var builder strings.Builder
for _, token := range tokens {
if token.Type == CharData {
builder.WriteString(token.Data)
}
}
t.chardataParsed = true
t.charData = builder.String()
return builder.String()
}
func (t *Token) SubParser() *Parser {
if t.Type != StartElement {
return nil
}
tokens := t.Element()
return NewFromTokens(tokens)
}