func AddSibling(sibling, n *Node) {
	for t := sibling.NextSibling; t != nil; t = t.NextSibling {
		sibling = t
	}
	n.Parent = sibling.Parent
	sibling.NextSibling = n
	n.PrevSibling = sibling
	n.NextSibling = nil
	if sibling.Parent != nil {
		sibling.Parent.LastChild = n
	}
}
AddSibling adds a new node 'n' as a sibling of a given node 'sibling'.
Note it is not necessarily true that the new node 'n' would be added
immediately after 'sibling'. If 'sibling' isn't the last child of its
parent, then the new node 'n' will be added at the end of the sibling
chain of their parent.
package xmlquery
import (
	"bytes"
	"encoding/xml"
	"fmt"
	"strings"
)
type NodeType uint
const (
	DocumentNode NodeType = iota
	DeclarationNode
	ElementNode
	TextNode
	CharDataNode
	CommentNode
	AttributeNode
)
type Attr struct {
	Name         xml.Name
	Value        string
	NamespaceURI string
}
type Node struct {
	Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
	Type         NodeType
	Data         string
	Prefix       string
	NamespaceURI string
	Attr         []Attr
	level int  
}
func (n *Node) InnerText() string {
	var output func(*bytes.Buffer, *Node)
	output = func(buf *bytes.Buffer, n *Node) {
		switch n.Type {
		case TextNode, CharDataNode:
			buf.WriteString(n.Data)
		case CommentNode:
		default:
			for child := n.FirstChild; child != nil; child = child.NextSibling {
				output(buf, child)
			}
		}
	}
	var buf bytes.Buffer
	output(&buf, n)
	return buf.String()
}
func (n *Node) sanitizedData(preserveSpaces bool) string {
	if preserveSpaces {
		return n.Data
	}
	return strings.TrimSpace(n.Data)
}
func calculatePreserveSpaces(n *Node, pastValue bool) bool {
	if attr := n.SelectAttr("xml:space"); attr == "preserve" {
		return true
	} else if attr == "default" {
		return false
	}
	return pastValue
}
func outputXML(buf *bytes.Buffer, n *Node, preserveSpaces bool) {
	preserveSpaces = calculatePreserveSpaces(n, preserveSpaces)
	switch n.Type {
	case TextNode:
		xml.EscapeText(buf, []byte(n.sanitizedData(preserveSpaces)))
		return
	case CharDataNode:
		buf.WriteString("<![CDATA[")
		buf.WriteString(n.Data)
		buf.WriteString("]]>")
		return
	case CommentNode:
		buf.WriteString("<!--")
		buf.WriteString(n.Data)
		buf.WriteString("-->")
		return
	case DeclarationNode:
		buf.WriteString("<?" + n.Data)
	default:
		if n.Prefix == "" {
			buf.WriteString("<" + n.Data)
		} else {
			buf.WriteString("<" + n.Prefix + ":" + n.Data)
		}
	}
	for _, attr := range n.Attr {
		if attr.Name.Space != "" {
			buf.WriteString(fmt.Sprintf(` %s:%s=`, attr.Name.Space, attr.Name.Local))
		} else {
			buf.WriteString(fmt.Sprintf(` %s=`, attr.Name.Local))
		}
		buf.WriteByte('"')
		xml.EscapeText(buf, []byte(attr.Value))
		buf.WriteByte('"')
	}
	if n.Type == DeclarationNode {
		buf.WriteString("?>")
	} else {
		buf.WriteString(">")
	}
	for child := n.FirstChild; child != nil; child = child.NextSibling {
		outputXML(buf, child, preserveSpaces)
	}
	if n.Type != DeclarationNode {
		if n.Prefix == "" {
			buf.WriteString(fmt.Sprintf("</%s>", n.Data))
		} else {
			buf.WriteString(fmt.Sprintf("</%s:%s>", n.Prefix, n.Data))
		}
	}
}
func (n *Node) OutputXML(self bool) string {
	preserveSpaces := calculatePreserveSpaces(n, false)
	var buf bytes.Buffer
	if self && n.Type != DocumentNode {
		outputXML(&buf, n, preserveSpaces)
	} else {
		for n := n.FirstChild; n != nil; n = n.NextSibling {
			outputXML(&buf, n, preserveSpaces)
		}
	}
	return buf.String()
}
func AddAttr(n *Node, key, val string) {
	var attr Attr
	if i := strings.Index(key, ":"); i > 0 {
		attr = Attr{
			Name:  xml.Name{Space: key[:i], Local: key[i+1:]},
			Value: val,
		}
	} else {
		attr = Attr{
			Name:  xml.Name{Local: key},
			Value: val,
		}
	}
	n.Attr = append(n.Attr, attr)
}
func AddChild(parent, n *Node) {
	n.Parent = parent
	n.NextSibling = nil
	if parent.FirstChild == nil {
		parent.FirstChild = n
		n.PrevSibling = nil
	} else {
		parent.LastChild.NextSibling = n
		n.PrevSibling = parent.LastChild
	}
	parent.LastChild = n
}