152 lines
2.3 KiB
Go
152 lines
2.3 KiB
Go
|
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
|
||
|
}
|