1
2
3
4
5
6 package x2j
7
8 import (
9 "strings"
10
11 "github.com/clbanning/mxj"
12 )
13
14
15
16
17
18
19
20 func PathsForTag(doc string, key string) ([]string, error) {
21 m, err := mxj.NewMapXml([]byte(doc))
22 if err != nil {
23 return nil, err
24 }
25
26 ss := PathsForKey(m, key)
27 return ss, nil
28 }
29
30
31
32 func PathForTagShortest(doc string, key string) (string, error) {
33 m, err := mxj.NewMapXml([]byte(doc))
34 if err != nil {
35 return "", err
36 }
37
38 s := PathForKeyShortest(m, key)
39 return s, nil
40 }
41
42
43
44 func BytePathsForTag(doc []byte, key string) ([]string, error) {
45 m, err := mxj.NewMapXml(doc)
46 if err != nil {
47 return nil, err
48 }
49
50 ss := PathsForKey(m, key)
51 return ss, nil
52 }
53
54
55
56 func BytePathForTagShortest(doc []byte, key string) (string, error) {
57 m, err := ByteDocToMap(doc)
58 if err != nil {
59 return "", err
60 }
61
62 s := PathForKeyShortest(m, key)
63 return s, nil
64 }
65
66
67
68 func PathsForKey(m map[string]interface{}, key string) []string {
69 breadbasket := make(map[string]bool,0)
70 breadcrumb := ""
71
72 hasKeyPath(breadcrumb, m, key, &breadbasket)
73 if len(breadbasket) == 0 {
74 return nil
75 }
76
77
78 res := make([]string,len(breadbasket))
79 var i int
80 for k,_ := range breadbasket {
81 res[i] = k
82 i++
83 }
84
85 return res
86 }
87
88
89
90 func PathForKeyShortest(m map[string]interface{}, key string) string {
91 paths := PathsForKey(m,key)
92
93 lp := len(paths)
94 if lp == 0 {
95 return ""
96 }
97 if lp == 1 {
98 return paths[0]
99 }
100
101 shortest := paths[0]
102 shortestLen := len(strings.Split(shortest,"."))
103
104 for i := 1 ; i < len(paths) ; i++ {
105 vlen := len(strings.Split(paths[i],"."))
106 if vlen < shortestLen {
107 shortest = paths[i]
108 shortestLen = vlen
109 }
110 }
111
112 return shortest
113 }
114
115
116
117 func hasKeyPath(crumb string, iv interface{}, key string, basket *map[string]bool) {
118 switch iv.(type) {
119 case map[string]interface{}:
120 vv := iv.(map[string]interface{})
121 if _, ok := vv[key]; ok {
122 if crumb == "" {
123 crumb = key
124 } else {
125 crumb += "." + key
126 }
127
128 (*basket)[crumb] = true
129 }
130
131 for k, v := range vv {
132
133 var nbc string
134 if crumb == "" {
135 nbc = k
136 } else {
137 nbc = crumb + "." + k
138 }
139 hasKeyPath(nbc, v, key, basket)
140 }
141 case []interface{}:
142
143 for _, v := range iv.([]interface{}) {
144 hasKeyPath(crumb, v, key, basket)
145 }
146 }
147 }
148
149
View as plain text