summaryrefslogtreecommitdiff
path: root/vendor/github.com/mitchellh/packer/vendor/github.com/ChrisTrenkamp/goxpath/tree/tree.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mitchellh/packer/vendor/github.com/ChrisTrenkamp/goxpath/tree/tree.go')
-rw-r--r--vendor/github.com/mitchellh/packer/vendor/github.com/ChrisTrenkamp/goxpath/tree/tree.go221
1 files changed, 221 insertions, 0 deletions
diff --git a/vendor/github.com/mitchellh/packer/vendor/github.com/ChrisTrenkamp/goxpath/tree/tree.go b/vendor/github.com/mitchellh/packer/vendor/github.com/ChrisTrenkamp/goxpath/tree/tree.go
new file mode 100644
index 00000000..c5d6333d
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/vendor/github.com/ChrisTrenkamp/goxpath/tree/tree.go
@@ -0,0 +1,221 @@
+package tree
+
+import (
+ "encoding/xml"
+ "sort"
+)
+
+//XMLSpace is the W3C XML namespace
+const XMLSpace = "http://www.w3.org/XML/1998/namespace"
+
+//NodePos is a helper for representing the node's document order
+type NodePos int
+
+//Pos returns the node's document order position
+func (n NodePos) Pos() int {
+ return int(n)
+}
+
+//NodeType is a safer way to determine a node's type than type assertions.
+type NodeType int
+
+//GetNodeType returns the node's type.
+func (t NodeType) GetNodeType() NodeType {
+ return t
+}
+
+//These are all the possible node types
+const (
+ NtAttr NodeType = iota
+ NtChd
+ NtComm
+ NtElem
+ NtNs
+ NtRoot
+ NtPi
+)
+
+//Node is a XPath result that is a node except elements
+type Node interface {
+ //ResValue prints the node's string value
+ ResValue() string
+ //Pos returns the node's position in the document order
+ Pos() int
+ //GetToken returns the xml.Token representation of the node
+ GetToken() xml.Token
+ //GetParent returns the parent node, which will always be an XML element
+ GetParent() Elem
+ //GetNodeType returns the node's type
+ GetNodeType() NodeType
+}
+
+//Elem is a XPath result that is an element node
+type Elem interface {
+ Node
+ //GetChildren returns the elements children.
+ GetChildren() []Node
+ //GetAttrs returns the attributes of the element
+ GetAttrs() []Node
+}
+
+//NSElem is a node that keeps track of namespaces.
+type NSElem interface {
+ Elem
+ GetNS() map[xml.Name]string
+}
+
+//NSBuilder is a helper-struct for satisfying the NSElem interface
+type NSBuilder struct {
+ NS map[xml.Name]string
+}
+
+//GetNS returns the namespaces found on the current element. It should not be
+//confused with BuildNS, which actually resolves the namespace nodes.
+func (ns NSBuilder) GetNS() map[xml.Name]string {
+ return ns.NS
+}
+
+type nsValueSort []NS
+
+func (ns nsValueSort) Len() int { return len(ns) }
+func (ns nsValueSort) Swap(i, j int) {
+ ns[i], ns[j] = ns[j], ns[i]
+}
+func (ns nsValueSort) Less(i, j int) bool {
+ return ns[i].Value < ns[j].Value
+}
+
+//BuildNS resolves all the namespace nodes of the element and returns them
+func BuildNS(t Elem) (ret []NS) {
+ vals := make(map[xml.Name]string)
+
+ if nselem, ok := t.(NSElem); ok {
+ buildNS(nselem, vals)
+
+ ret = make([]NS, 0, len(vals))
+ i := 1
+
+ for k, v := range vals {
+ if !(k.Local == "xmlns" && k.Space == "" && v == "") {
+ ret = append(ret, NS{
+ Attr: xml.Attr{Name: k, Value: v},
+ Parent: t,
+ NodeType: NtNs,
+ })
+ i++
+ }
+ }
+
+ sort.Sort(nsValueSort(ret))
+ for i := range ret {
+ ret[i].NodePos = NodePos(t.Pos() + i + 1)
+ }
+ }
+
+ return ret
+}
+
+func buildNS(x NSElem, ret map[xml.Name]string) {
+ if x.GetNodeType() == NtRoot {
+ return
+ }
+
+ if nselem, ok := x.GetParent().(NSElem); ok {
+ buildNS(nselem, ret)
+ }
+
+ for k, v := range x.GetNS() {
+ ret[k] = v
+ }
+}
+
+//NS is a namespace node.
+type NS struct {
+ xml.Attr
+ Parent Elem
+ NodePos
+ NodeType
+}
+
+//GetToken returns the xml.Token representation of the namespace.
+func (ns NS) GetToken() xml.Token {
+ return ns.Attr
+}
+
+//GetParent returns the parent node of the namespace.
+func (ns NS) GetParent() Elem {
+ return ns.Parent
+}
+
+//ResValue returns the string value of the namespace
+func (ns NS) ResValue() string {
+ return ns.Attr.Value
+}
+
+//GetAttribute is a convenience function for getting the specified attribute from an element.
+//false is returned if the attribute is not found.
+func GetAttribute(n Elem, local, space string) (xml.Attr, bool) {
+ attrs := n.GetAttrs()
+ for _, i := range attrs {
+ attr := i.GetToken().(xml.Attr)
+ if local == attr.Name.Local && space == attr.Name.Space {
+ return attr, true
+ }
+ }
+ return xml.Attr{}, false
+}
+
+//GetAttributeVal is like GetAttribute, except it returns the attribute's value.
+func GetAttributeVal(n Elem, local, space string) (string, bool) {
+ attr, ok := GetAttribute(n, local, space)
+ return attr.Value, ok
+}
+
+//GetAttrValOrEmpty is like GetAttributeVal, except it returns an empty string if
+//the attribute is not found instead of false.
+func GetAttrValOrEmpty(n Elem, local, space string) string {
+ val, ok := GetAttributeVal(n, local, space)
+ if !ok {
+ return ""
+ }
+ return val
+}
+
+//FindNodeByPos finds a node from the given position. Returns nil if the node
+//is not found.
+func FindNodeByPos(n Node, pos int) Node {
+ if n.Pos() == pos {
+ return n
+ }
+
+ if elem, ok := n.(Elem); ok {
+ chldrn := elem.GetChildren()
+ for i := 1; i < len(chldrn); i++ {
+ if chldrn[i-1].Pos() <= pos && chldrn[i].Pos() > pos {
+ return FindNodeByPos(chldrn[i-1], pos)
+ }
+ }
+
+ if len(chldrn) > 0 {
+ if chldrn[len(chldrn)-1].Pos() <= pos {
+ return FindNodeByPos(chldrn[len(chldrn)-1], pos)
+ }
+ }
+
+ attrs := elem.GetAttrs()
+ for _, i := range attrs {
+ if i.Pos() == pos {
+ return i
+ }
+ }
+
+ ns := BuildNS(elem)
+ for _, i := range ns {
+ if i.Pos() == pos {
+ return i
+ }
+ }
+ }
+
+ return nil
+}