Next / Previous / Contents / Shipman's homepage

24. Sox._buildAttrs(): Build XML attributes from a dictionary

sox.py
# - - -   S o x . _ b u i l d A t t r s

    def _buildAttrs(self, attribs):
        '''Format XML attributes.

          [ attribs is a dictionary whose keys are xml-names and
            whose values are all unicode-okay ->
              if attribs is empty ->
                return ""
              else ->
                return " " + (a space-separated list of items A=V
                where each A is a key in attribs as unicode and
                V is escaped-attribute(the related value as
                unicode)) ]
        '''

We return the empty string if there are no attributes. Without this case, the start tag might look like “<name >”. If there are any attributes, we start the result list with a single empty string, which will cause the result to start with one space that separates the tag name from the first attribute in the start tag.

sox.py
        #-- 1
        if len(attribs) == 0:
            return u''
        else:
            result = [u'']

        #-- 2
        # [ if (the keys of attribs are all xml-names) and
        #   (the values of attribs are all unicode-okay) ->
        #     result  +:=  unicode values of the form "K=V" where
        #         each K is an element of attrib as unicode
        #         and each V is the corresponding value as
        #         unicode
        #   else ->
        #     result  +:=  (anything)
        #     raise SoxError ]
        for key, value in attribs.items():
            #-- 2 body
            # [ if (key is an xml-name) and (value is unicode-okay) ->
            #     result  +:=  (a string of the form K=V where K
            #         is (key) as unicode and V is (value) as
            #         unicode with forbidden characters escaped
            #   else -> raise SoxError ]
            #-- 2.1
            # [ if key is an xml-name ->
            #     uniKey  :=  key as unicode
            #   else -> raise SoxError ]
            uniKey = self._nameCheck(key)

The “K=V” item we append to the result list must actually be ASCII. We use the unicode.encode() function with the 'xmlcharrefreplace' option so that non-ASCII characters are escaped, e.g., code point 0xC0 will be rendered as "&192;".

sox.py
            #-- 2.2
            # [ if value is unicode-okay ->
            #     uniValue  :=  value as unicode with forbidden
            #         characters escaped
            #   else -> raise SoxError ]
            uniValue = self._attrEscape(value)

Now we have the attribute name and value in Unicode form.

sox.py
            #-- 2.3
            # [ result  :=  uniKey + '="' + uniValue + '"' ]
            attrPair = ('%s="%s"' % (uniKey, uniValue))
            result.append(attrPair)

        #-- 3
        return u' '.join(result).encode('utf-8')