sort.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package etreeutils
  2. import "github.com/beevik/etree"
  3. // SortedAttrs provides sorting capabilities, compatible with XML C14N, on top
  4. // of an []etree.Attr
  5. type SortedAttrs []etree.Attr
  6. func (a SortedAttrs) Len() int {
  7. return len(a)
  8. }
  9. func (a SortedAttrs) Swap(i, j int) {
  10. a[i], a[j] = a[j], a[i]
  11. }
  12. func (a SortedAttrs) Less(i, j int) bool {
  13. // This is the best reference I've found on sort order:
  14. // http://dst.lbl.gov/~ksb/Scratch/XMLC14N.html
  15. // If attr j is a default namespace declaration, attr i may
  16. // not be strictly "less" than it.
  17. if a[j].Space == defaultPrefix && a[j].Key == xmlnsPrefix {
  18. return false
  19. }
  20. // Otherwise, if attr i is a default namespace declaration, it
  21. // must be less than anything else.
  22. if a[i].Space == defaultPrefix && a[i].Key == xmlnsPrefix {
  23. return true
  24. }
  25. // Next, namespace prefix declarations, sorted by prefix, come before
  26. // anythign else.
  27. if a[i].Space == xmlnsPrefix {
  28. if a[j].Space == xmlnsPrefix {
  29. return a[i].Key < a[j].Key
  30. }
  31. return true
  32. }
  33. if a[j].Space == xmlnsPrefix {
  34. return false
  35. }
  36. // Then come unprefixed attributes, sorted by key.
  37. if a[i].Space == defaultPrefix {
  38. if a[j].Space == defaultPrefix {
  39. return a[i].Key < a[j].Key
  40. }
  41. return true
  42. }
  43. if a[j].Space == defaultPrefix {
  44. return false
  45. }
  46. // Wow. We're still going. Finally, attributes in the same namespace should be
  47. // sorted by key. Attributes in different namespaces should be sorted by the
  48. // actual namespace (_not_ the prefix). For now just use the prefix.
  49. if a[i].Space == a[j].Space {
  50. return a[i].Key < a[j].Key
  51. }
  52. return a[i].Space < a[j].Space
  53. }