11package tree
22
33import (
4+ "cmp"
45 "fmt"
56 "slices"
67
@@ -13,16 +14,16 @@ import (
1314// If honorNamespace is set, the xml elements will carry their respective namespace attributes.
1415// If operationWithNamespace is set, the operation attributes added to the to be deleted alements will also carry the Netconf Base namespace.
1516// If useOperationRemove is set, the remove operation will be used for deletes, instead of the delete operation.
16- func (s * sharedEntryAttributes ) ToXML (onlyNewOrUpdated , honorNamespace , operationWithNamespace , useOperationRemove bool , ordered bool ) (* etree.Document , error ) {
17+ func (s * sharedEntryAttributes ) ToXML (onlyNewOrUpdated , honorNamespace , operationWithNamespace , useOperationRemove bool , ordering OrderingMethod ) (* etree.Document , error ) {
1718 doc := etree .NewDocument ()
18- _ , err := s .toXmlInternal (& doc .Element , onlyNewOrUpdated , honorNamespace , operationWithNamespace , useOperationRemove , ordered )
19+ _ , err := s .toXmlInternal (& doc .Element , onlyNewOrUpdated , honorNamespace , operationWithNamespace , useOperationRemove , ordering )
1920 if err != nil {
2021 return nil , err
2122 }
2223 return doc , nil
2324}
2425
25- func (s * sharedEntryAttributes ) toXmlInternal (parent * etree.Element , onlyNewOrUpdated bool , honorNamespace bool , operationWithNamespace bool , useOperationRemove bool , ordered bool ) (doAdd bool , err error ) {
26+ func (s * sharedEntryAttributes ) toXmlInternal (parent * etree.Element , onlyNewOrUpdated bool , honorNamespace bool , operationWithNamespace bool , useOperationRemove bool , ordering OrderingMethod ) (doAdd bool , err error ) {
2627
2728 switch s .schema .GetSchema ().(type ) {
2829 case nil :
@@ -42,31 +43,45 @@ func (s *sharedEntryAttributes) toXmlInternal(parent *etree.Element, onlyNewOrUp
4243
4344 childs := s .filterActiveChoiceCaseChilds ()
4445
45- if ordered {
46- keys := make ([]string , 0 , len (childs ))
47- for k := range childs {
48- keys = append (keys , k )
49- }
50- slices .Sort (keys )
46+ keys := make ([]string , 0 , len (childs ))
47+ for k := range childs {
48+ keys = append (keys , k )
49+ }
5150
52- for _ , k := range keys {
53- // recurse the call
54- // no additional element is created, since we're on a key level, so add to parent element
55- doAdd , err := childs [k ].toXmlInternal (parent , onlyNewOrUpdated , honorNamespace , operationWithNamespace , useOperationRemove , ordered )
56- if err != nil {
57- return false , err
58- }
59- // only if there was something added in the childs, the element itself is meant to be added.
60- // we keep track of that via overAllDoAdd.
61- overallDoAdd = doAdd || overallDoAdd
51+ switch ordering {
52+ case Alphabetical :
53+ slices .Sort (keys )
54+ case None :
55+ case SchemaBound :
56+ schemaParent , _ := s .GetFirstAncestorWithSchema ()
57+ if schemaParent == nil {
58+ return false , fmt .Errorf ("no ancestor has schema for %v" , s )
6259 }
63- return overallDoAdd , nil
60+ schemaKeys := schemaParent .GetSchemaKeys ()
61+ slices .SortFunc (keys , func (a , b string ) int {
62+ aIdx := slices .Index (schemaKeys , a )
63+ bIdx := slices .Index (schemaKeys , b )
64+ switch {
65+ case aIdx == - 1 && bIdx == - 1 :
66+ // if neither are keys, sort them against each other
67+ return cmp .Compare (a , b )
68+ case aIdx == - 1 :
69+ return 1
70+ case bIdx == - 1 :
71+ return - 1
72+ default :
73+ return cmp .Compare (aIdx , bIdx )
74+ }
75+ })
76+
77+ default :
78+ return false , fmt .Errorf ("unknown ordering method: %v" , ordering )
6479 }
6580
66- for _ , c := range childs {
81+ for _ , k := range keys {
6782 // recurse the call
6883 // no additional element is created, since we're on a key level, so add to parent element
69- doAdd , err := c .toXmlInternal (parent , onlyNewOrUpdated , honorNamespace , operationWithNamespace , useOperationRemove , ordered )
84+ doAdd , err := childs [ k ] .toXmlInternal (parent , onlyNewOrUpdated , honorNamespace , operationWithNamespace , useOperationRemove , ordering )
7085 if err != nil {
7186 return false , err
7287 }
@@ -87,8 +102,16 @@ func (s *sharedEntryAttributes) toXmlInternal(parent *etree.Element, onlyNewOrUp
87102 return false , err
88103 }
89104
90- if ordered {
105+ switch ordering {
106+ case Alphabetical :
107+ slices .SortFunc (childs , func (a , b Entry ) int {
108+ return cmp .Compare (a .PathName (), b .PathName ())
109+ })
110+ case SchemaBound :
91111 slices .SortFunc (childs , getListEntrySortFunc (s ))
112+ case None :
113+ default :
114+ return false , fmt .Errorf ("unknown ordering method: %v" , ordering )
92115 }
93116
94117 // go through the childs creating the xml elements
@@ -98,7 +121,7 @@ func (s *sharedEntryAttributes) toXmlInternal(parent *etree.Element, onlyNewOrUp
98121 // process the honorNamespace instruction
99122 xmlAddNamespaceConditional (s , s .parent , newElem , honorNamespace )
100123 // recurse the call
101- doAdd , err := child .toXmlInternal (newElem , onlyNewOrUpdated , honorNamespace , operationWithNamespace , useOperationRemove , ordered )
124+ doAdd , err := child .toXmlInternal (newElem , onlyNewOrUpdated , honorNamespace , operationWithNamespace , useOperationRemove , ordering )
102125 if err != nil {
103126 return false , err
104127 }
@@ -147,8 +170,21 @@ func (s *sharedEntryAttributes) toXmlInternal(parent *etree.Element, onlyNewOrUp
147170 keys = append (keys , k )
148171 }
149172
150- if ordered {
173+ switch ordering {
174+ case Alphabetical :
151175 slices .Sort (keys )
176+ case SchemaBound :
177+ if s .parent == nil {
178+ slices .Sort (keys )
179+ } else {
180+ cldrn := s .schema .GetContainer ().GetChildren ()
181+ slices .SortFunc (keys , func (a , b string ) int {
182+ return cmp .Compare (slices .Index (cldrn , a ), slices .Index (cldrn , b ))
183+ })
184+ }
185+ case None :
186+ default :
187+ return false , fmt .Errorf ("unknown ordering method: %v" , ordering )
152188 }
153189
154190 // iterate through all the childs
@@ -165,7 +201,7 @@ func (s *sharedEntryAttributes) toXmlInternal(parent *etree.Element, onlyNewOrUp
165201 newElem = parent
166202 }
167203 // recurse the call to all the children
168- doAdd , err := s .childs [k ].toXmlInternal (newElem , onlyNewOrUpdated , honorNamespace , operationWithNamespace , useOperationRemove , ordered )
204+ doAdd , err := s .childs [k ].toXmlInternal (newElem , onlyNewOrUpdated , honorNamespace , operationWithNamespace , useOperationRemove , ordering )
169205 if err != nil {
170206 return false , err
171207 }
0 commit comments