misc.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. )
  12. // Return the root element of the Map. If there is not a single key in Map,
  13. // then an error is returned.
  14. func (m Map) Root() (string, error) {
  15. mm := map[string]interface{}(m)
  16. if len(mm) != 1 {
  17. return "", fmt.Errorf("Map does not have singleton root. Len: %d.", len(mm))
  18. }
  19. for k, _ := range mm {
  20. return k, nil
  21. }
  22. return "", nil
  23. }
  24. // If the path is an element with sub-elements, return a list of the sub-element
  25. // keys. (The list is alphabeticly sorted.) NOTE: Map keys that are prefixed with
  26. // '-', a hyphen, are considered attributes; see m.Attributes(path).
  27. func (m Map) Elements(path string) ([]string, error) {
  28. e, err := m.ValueForPath(path)
  29. if err != nil {
  30. return nil, err
  31. }
  32. switch e.(type) {
  33. case map[string]interface{}:
  34. ee := e.(map[string]interface{})
  35. elems := make([]string, len(ee))
  36. var i int
  37. for k, _ := range ee {
  38. if k[:1] == "-" {
  39. continue // skip attributes
  40. }
  41. elems[i] = k
  42. i++
  43. }
  44. elems = elems[:i]
  45. // alphabetic sort keeps things tidy
  46. sort.Strings(elems)
  47. return elems, nil
  48. }
  49. return nil, fmt.Errorf("no elements for path: %s", path)
  50. }
  51. // If the path is an element with attributes, return a list of the attribute
  52. // keys. (The list is alphabeticly sorted.) NOTE: Map keys that are not prefixed with
  53. // '-', a hyphen, are not treated as attributes; see m.Elements(path).
  54. func (m Map) Attributes(path string) ([]string, error) {
  55. a, err := m.ValueForPath(path)
  56. if err != nil {
  57. return nil, err
  58. }
  59. switch a.(type) {
  60. case map[string]interface{}:
  61. aa := a.(map[string]interface{})
  62. attrs := make([]string, len(aa))
  63. var i int
  64. for k, _ := range aa {
  65. if k[:1] != "-" {
  66. continue // skip non-attributes
  67. }
  68. attrs[i] = k[1:]
  69. i++
  70. }
  71. attrs = attrs[:i]
  72. // alphabetic sort keeps things tidy
  73. sort.Strings(attrs)
  74. return attrs, nil
  75. }
  76. return nil, fmt.Errorf("no attributes for path: %s", path)
  77. }