canonicalize.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package etreeutils
  2. import (
  3. "sort"
  4. "strings"
  5. "github.com/beevik/etree"
  6. )
  7. // TransformExcC14n transforms the passed element into xml-exc-c14n form.
  8. func TransformExcC14n(el *etree.Element, inclusiveNamespacesPrefixList string) error {
  9. prefixes := strings.Fields(inclusiveNamespacesPrefixList)
  10. prefixSet := make(map[string]struct{}, len(prefixes))
  11. for _, prefix := range prefixes {
  12. prefixSet[prefix] = struct{}{}
  13. }
  14. err := transformExcC14n(DefaultNSContext, DefaultNSContext, el, prefixSet)
  15. if err != nil {
  16. return err
  17. }
  18. return nil
  19. }
  20. func transformExcC14n(ctx, declared NSContext, el *etree.Element, inclusiveNamespaces map[string]struct{}) error {
  21. scope, err := ctx.SubContext(el)
  22. if err != nil {
  23. return err
  24. }
  25. visiblyUtilizedPrefixes := map[string]struct{}{
  26. el.Space: struct{}{},
  27. }
  28. filteredAttrs := []etree.Attr{}
  29. // Filter out all namespace declarations
  30. for _, attr := range el.Attr {
  31. switch {
  32. case attr.Space == xmlnsPrefix:
  33. if _, ok := inclusiveNamespaces[attr.Key]; ok {
  34. visiblyUtilizedPrefixes[attr.Key] = struct{}{}
  35. }
  36. case attr.Space == defaultPrefix && attr.Key == xmlnsPrefix:
  37. if _, ok := inclusiveNamespaces[defaultPrefix]; ok {
  38. visiblyUtilizedPrefixes[defaultPrefix] = struct{}{}
  39. }
  40. default:
  41. if attr.Space != defaultPrefix {
  42. visiblyUtilizedPrefixes[attr.Space] = struct{}{}
  43. }
  44. filteredAttrs = append(filteredAttrs, attr)
  45. }
  46. }
  47. el.Attr = filteredAttrs
  48. declared = declared.Copy()
  49. // Declare all visibly utilized prefixes that are in-scope but haven't
  50. // been declared in the canonicalized form yet. These might have been
  51. // declared on this element but then filtered out above, or they might
  52. // have been declared on an ancestor (before canonicalization) which
  53. // didn't visibly utilize and thus had them removed.
  54. for prefix := range visiblyUtilizedPrefixes {
  55. // Skip redundant declarations - they have to already have the same
  56. // value.
  57. if declaredNamespace, ok := declared.prefixes[prefix]; ok {
  58. if value, ok := scope.prefixes[prefix]; ok && declaredNamespace == value {
  59. continue
  60. }
  61. }
  62. namespace, err := scope.LookupPrefix(prefix)
  63. if err != nil {
  64. return err
  65. }
  66. el.Attr = append(el.Attr, declared.declare(prefix, namespace))
  67. }
  68. sort.Sort(SortedAttrs(el.Attr))
  69. // Transform child elements
  70. for _, child := range el.ChildElements() {
  71. err := transformExcC14n(scope, declared, child, inclusiveNamespaces)
  72. if err != nil {
  73. return err
  74. }
  75. }
  76. return nil
  77. }