func ParseDecoder(d *xml.Decoder) (*Node, error) {
	var nodes []Node
	var text []byte
	nodes = append(nodes, Node{kind: startNode})
	for {
		t, err := d.Token()
		if err == io.EOF {
			break
		}
		if err != nil {
			return nil, err
		}
		switch t := t.(type) {
		case xml.EndElement:
			nodes = append(nodes, Node{
				kind: endNode,
			})
		case xml.StartElement:
			nodes = append(nodes, Node{
				kind: startNode,
				name: t.Name,
			})
			for _, attr := range t.Attr {
				nodes = append(nodes, Node{
					kind: attrNode,
					name: attr.Name,
					attr: attr.Value,
				})
			}
		case xml.CharData:
			texti := len(text)
			text = append(text, t...)
			nodes = append(nodes, Node{
				kind: textNode,
				text: text[texti : texti+len(t)],
			})
		case xml.Comment:
			texti := len(text)
			text = append(text, t...)
			nodes = append(nodes, Node{
				kind: commentNode,
				text: text[texti : texti+len(t)],
			})
		case xml.ProcInst:
			texti := len(text)
			text = append(text, t.Inst...)
			nodes = append(nodes, Node{
				kind: procInstNode,
				name: xml.Name{Local: t.Target},
				text: text[texti : texti+len(t.Inst)],
			})
		}
	}
	nodes = append(nodes, Node{kind: endNode})
	stack := make([]*Node, 0, len(nodes))
	downs := make([]*Node, len(nodes))
	downCount := 0
	for pos := range nodes {
		switch nodes[pos].kind {
		case startNode, attrNode, textNode, commentNode, procInstNode:
			node := &nodes[pos]
			node.nodes = nodes
			node.pos = pos
			if len(stack) > 0 {
				node.up = stack[len(stack)-1]
			}
			if node.kind == startNode {
				stack = append(stack, node)
			} else {
				node.end = pos + 1
			}
		case endNode:
			node := stack[len(stack)-1]
			node.end = pos
			stack = stack[:len(stack)-1]
			node.down = downs[downCount:downCount]
			for i := node.pos + 1; i < node.end; i++ {
				if nodes[i].up == node {
					switch nodes[i].kind {
					case startNode, textNode, commentNode, procInstNode:
						node.down = append(node.down, &nodes[i])
						downCount++
					}
				}
			}
			if len(stack) == 0 {
				return node, nil
			}
		}
	}
	return nil, io.EOF
}
ParseDecoder parses the xml document being decoded by d and returns
its root node.
package xmlpath
import (
	"golang.org/x/net/html"
	"encoding/xml"
	"io"
	"strings"
)
type Node struct {
	kind nodeKind
	name xml.Name
	attr string
	text []byte
	nodes []Node
	pos   int
	end   int
	up   *Node
	down []*Node
}
type nodeKind int
const (
	anyNode nodeKind = iota
	startNode
	endNode
	attrNode
	textNode
	commentNode
	procInstNode
)
func (node *Node) String() string {
	if node.kind == attrNode {
		return node.attr
	}
	return string(node.Bytes())
}
func (node *Node) Bytes() []byte {
	if node.kind == attrNode {
		return []byte(node.attr)
	}
	if node.kind != startNode {
		return node.text
	}
	size := 0
	for i := node.pos; i < node.end; i++ {
		if node.nodes[i].kind == textNode {
			size += len(node.nodes[i].text)
		}
	}
	text := make([]byte, 0, size)
	for i := node.pos; i < node.end; i++ {
		if node.nodes[i].kind == textNode {
			text = append(text, node.nodes[i].text...)
		}
	}
	return text
}
func (node *Node) equals(s string) bool {
	if node.kind == attrNode {
		return s == node.attr
	}
	if node.kind != startNode {
		if len(s) != len(node.text) {
			return false
		}
		for i := range s {
			if s[i] != node.text[i] {
				return false
			}
		}
		return true
	}
	si := 0
	for i := node.pos; i < node.end; i++ {
		if node.nodes[i].kind == textNode {
			for _, c := range node.nodes[i].text {
				if si > len(s) {
					return false
				}
				if s[si] != c {
					return false
				}
				si++
			}
		}
	}
	return si == len(s)
}
func (node *Node) contains(s string) (ok bool) {
	if len(s) == 0 {
		return true
	}
	if node.kind == attrNode {
		return strings.Contains(node.attr, s)
	}
	s0 := s[0]
	for i := node.pos; i < node.end; i++ {
		if node.nodes[i].kind == textNode {
			text := node.nodes[i].text
		NextTry:
			for ci, c := range text {
				if c != s0 {
					continue
				}
				si := 1
				for ci++; ci < len(text) && si < len(s); ci++ {
					if s[si] != text[ci] {
						continue NextTry
					}
					si++
				}
				if si == len(s) {
					return true
				}
				for j := i + 1; j < node.end; j++ {
					if node.nodes[j].kind == textNode {
						for _, c := range node.nodes[j].text {
							if s[si] != c {
								continue NextTry
							}
							si++
							if si == len(s) {
								return true
							}
						}
					}
				}
			}
		}
	}
	return false
}
func Parse(r io.Reader) (*Node, error) {
	return ParseDecoder(xml.NewDecoder(r))
}