misc.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // Copyright 2016 Charles Banning. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file
  4. // misc.go - mimic functions (+others) called out in:
  5. // https://groups.google.com/forum/#!topic/golang-nuts/jm_aGsJNbdQ
  6. // Primarily these methods let you retrive XML structure information.
  7. package mxj
  8. import (
  9. "fmt"
  10. "sort"
  11. "strings"
  12. )
  13. // Return the root element of the Map. If there is not a single key in Map,
  14. // then an error is returned.
  15. func (mv Map) Root() (string, error) {
  16. mm := map[string]interface{}(mv)
  17. if len(mm) != 1 {
  18. return "", fmt.Errorf("Map does not have singleton root. Len: %d.", len(mm))
  19. }
  20. for k, _ := range mm {
  21. return k, nil
  22. }
  23. return "", nil
  24. }
  25. // If the path is an element with sub-elements, return a list of the sub-element
  26. // keys. (The list is alphabeticly sorted.) NOTE: Map keys that are prefixed with
  27. // '-', a hyphen, are considered attributes; see m.Attributes(path).
  28. func (mv Map) Elements(path string) ([]string, error) {
  29. e, err := mv.ValueForPath(path)
  30. if err != nil {
  31. return nil, err
  32. }
  33. switch e.(type) {
  34. case map[string]interface{}:
  35. ee := e.(map[string]interface{})
  36. elems := make([]string, len(ee))
  37. var i int
  38. for k, _ := range ee {
  39. if len(attrPrefix) > 0 && strings.Index(k, attrPrefix) == 0 {
  40. continue // skip attributes
  41. }
  42. elems[i] = k
  43. i++
  44. }
  45. elems = elems[:i]
  46. // alphabetic sort keeps things tidy
  47. sort.Strings(elems)
  48. return elems, nil
  49. }
  50. return nil, fmt.Errorf("no elements for path: %s", path)
  51. }
  52. // If the path is an element with attributes, return a list of the attribute
  53. // keys. (The list is alphabeticly sorted.) NOTE: Map keys that are not prefixed with
  54. // '-', a hyphen, are not treated as attributes; see m.Elements(path). Also, if the
  55. // attribute prefix is "" - SetAttrPrefix("") or PrependAttrWithHyphen(false) - then
  56. // there are no identifiable attributes.
  57. func (mv Map) Attributes(path string) ([]string, error) {
  58. a, err := mv.ValueForPath(path)
  59. if err != nil {
  60. return nil, err
  61. }
  62. switch a.(type) {
  63. case map[string]interface{}:
  64. aa := a.(map[string]interface{})
  65. attrs := make([]string, len(aa))
  66. var i int
  67. for k, _ := range aa {
  68. if len(attrPrefix) == 0 || strings.Index(k, attrPrefix) != 0 {
  69. continue // skip non-attributes
  70. }
  71. attrs[i] = k[len(attrPrefix):]
  72. i++
  73. }
  74. attrs = attrs[:i]
  75. // alphabetic sort keeps things tidy
  76. sort.Strings(attrs)
  77. return attrs, nil
  78. }
  79. return nil, fmt.Errorf("no attributes for path: %s", path)
  80. }