"""Utilities for XML generation/parsing."""importrefromxml.sax.saxutilsimportXMLGeneratorclassUnserializableContentError(ValueError):passclassSimplerXMLGenerator(XMLGenerator):defaddQuickElement(self,name,contents=None,attrs=None):"Convenience method for adding an element with no children"ifattrsisNone:attrs={}self.startElement(name,attrs)ifcontentsisnotNone:self.characters(contents)self.endElement(name)defcharacters(self,content):ifcontentandre.search(r"[\x00-\x08\x0B-\x0C\x0E-\x1F]",content):# Fail loudly when content has control chars (unsupported in XML 1.0)# See https://www.w3.org/International/questions/qa-controlsraiseUnserializableContentError("Control characters are not supported in XML 1.0")XMLGenerator.characters(self,content)defstartElement(self,name,attrs):# Sort attrs for a deterministic output.sorted_attrs=dict(sorted(attrs.items()))ifattrselseattrssuper().startElement(name,sorted_attrs)