package graph import ( "errors" "log" ) var attributeNameLaw map[rune]struct{} = make(map[rune]struct{}) func init() { for _, c := range "abcdefghijklmnopqrstuvwsyzABCDEFGHIJKLMNOPQRSTUVWSYZ-_" { attributeNameLaw[c] = struct{}{} } } type Range struct { Start int End int } type ElementTag struct { Range } type Element struct { Range Tag *ElementTag Attributes []*Attribute Source []rune Children []*Element } type Attribute struct { Range Key Range Value Range } func (e *Element) GetTagName() string { return string(e.Source[e.Tag.Start:e.Tag.End]) } func GetTag(source []rune, cur int) (*ElementTag, int) { for i := cur; i < len(source); i++ { c := source[i] if c == ' ' { return &ElementTag{Range{cur, i - 1}}, i } } return nil, -1 } func SkipAttribute(source []rune, cur int) int { for i := cur; i < len(source); i++ { c := source[i] if c == ' ' || c == '>' { return i - 1 } } panic(errors.New("over the range of the next attribute")) } func GetAttribute(source []rune, cur int) *Range { } func GetAttributes(source []rune, cur int) []*Attribute { var attrs []*Attribute LOOP_TOP: for i := cur; i < len(source); i++ { c := source[i] switch c { case '>': break LOOP_TOP case '/': if source[i+1] == '>' { break LOOP_TOP } case ' ': continue default: attr := &Attribute{} attr.Range.Start = i for ; i < len(source); i++ { c = source[i] if _, ok := attributeNameLaw[c]; !ok { i = SkipAttribute(source, i) break } else { if c == ' ' || c == '>' { attr.Range.End = i break } } } } } return attrs } func ParseChild(parent *Element, cur int) *Element { start := cur end := start child := &Element{} child.Tag, cur = GetTag(parent.Source, start) GetAttributes(parent.Source, cur) for i := cur; i < len(parent.Source); i++ { c := parent.Source[i] if c == '>' { end = i - 1 return child } } return nil } func GetChildren(parent *Element) { // GetChild for i := parent.Range.Start; i < parent.Range.End; i++ { c := parent.Source[i] if c == '<' { tag := ParseChild(parent, i) log.Println(tag) } } } func ParseXML(data []byte) *Element { source := []rune(string(data)) root := &Element{tag: nil, Source: source, Pos: Range{0, len(source)}} return root }