@@ -659,7 +659,7 @@ Functions
659
659
660
660
661
661
.. function :: tostring(element, encoding="us-ascii", method="xml", *, \
662
- xml_declaration=None, default_namespace=None,
662
+ xml_declaration=None, default_namespace=None, \
663
663
short_empty_elements=True)
664
664
665
665
Generates a string representation of an XML element, including all
@@ -677,9 +677,13 @@ Functions
677
677
.. versionadded :: 3.8
678
678
The *xml_declaration * and *default_namespace * parameters.
679
679
680
+ .. versionchanged :: 3.8
681
+ The :func: `tostring ` function now preserves the attribute order
682
+ specified by the user.
683
+
680
684
681
685
.. function :: tostringlist(element, encoding="us-ascii", method="xml", *, \
682
- xml_declaration=None, default_namespace=None,
686
+ xml_declaration=None, default_namespace=None, \
683
687
short_empty_elements=True)
684
688
685
689
Generates a string representation of an XML element, including all
@@ -700,6 +704,10 @@ Functions
700
704
.. versionadded :: 3.8
701
705
The *xml_declaration * and *default_namespace * parameters.
702
706
707
+ .. versionchanged :: 3.8
708
+ The :func: `tostringlist ` function now preserves the attribute order
709
+ specified by the user.
710
+
703
711
704
712
.. function :: XML(text, parser=None)
705
713
@@ -930,6 +938,36 @@ Element Objects
930
938
if element is None:
931
939
print("element not found")
932
940
941
+ Prior to Python 3.8, the serialisation order of the XML attributes of
942
+ elements was artificially made predictable by sorting the attributes by
943
+ their name. Based on the now guaranteed ordering of dicts, this arbitrary
944
+ reordering was removed in Python 3.8 to preserve the order in which
945
+ attributes were originally parsed or created by user code.
946
+
947
+ In general, user code should try not to depend on a specific ordering of
948
+ attributes, given that the `XML Information Set
949
+ <https://www.w3.org/TR/xml-infoset/> `_ explicitly excludes the attribute
950
+ order from conveying information. Code should be prepared to deal with
951
+ any ordering on input. In cases where deterministic XML output is required,
952
+ e.g. for cryptographic signing or test data sets, canonical serialisation
953
+ is available with the :func: `canonicalize ` function.
954
+
955
+ In cases where canonical output is not applicable but a specific attribute
956
+ order is still desirable on output, code should aim for creating the
957
+ attributes directly in the desired order, to avoid perceptual mismatches
958
+ for readers of the code. In cases where this is difficult to achieve, a
959
+ recipe like the following can be applied prior to serialisation to enforce
960
+ an order independently from the Element creation::
961
+
962
+ def reorder_attributes(root):
963
+ for el in root.iter():
964
+ attrib = el.attrib
965
+ if len(attrib) > 1:
966
+ # adjust attribute order, e.g. by sorting
967
+ attribs = sorted(attrib.items())
968
+ attrib.clear()
969
+ attrib.update(attribs)
970
+
933
971
934
972
.. _elementtree-elementtree-objects :
935
973
0 commit comments