docs: def renameID(doc, idFrom, idTo, identifiedElements, referencedIDs):
      """
      Changes the ID name from idFrom to idTo, on the declaring element
      as well as all references in the document doc.
  
      Updates identifiedElements and referencedIDs.
      Does not handle the case where idTo is already the ID name
      of another element in doc.
  
      Returns the number of bytes saved by this replacement.
      """
  
      num = 0
  
      definingNode = identifiedElements[idFrom]
      definingNode.setAttribute("id", idTo)
      del identifiedElements[idFrom]
      identifiedElements[idTo] = definingNode
      num += len(idFrom) - len(idTo)
  
      # Update references to renamed node
      referringNodes = referencedIDs.get(idFrom)
      if referringNodes is not None:
  
          # Look for the idFrom ID name in each of the referencing elements,
          # exactly like findReferencedElements would.
          # Cyn: Duplicated processing!
  
          for node in referringNodes:
              # if this node is a style element, parse its text into CSS
              if node.nodeName == 'style' and node.namespaceURI == NS['SVG']:
                  # node.firstChild will be either a CDATA or a Text node now
                  if node.firstChild is not None:
                      # concatenate the value of all children, in case
                      # there's a CDATASection node surrounded by whitespace
                      # nodes
                      # (node.normalize() will NOT work here, it only acts on Text nodes)
                      oldValue = "".join([child.nodeValue for child in node.childNodes])
                      # not going to reparse the whole thing
                      newValue = oldValue.replace('url(#' + idFrom + ')', 'url(#' + idTo + ')')
                      newValue = newValue.replace("url(#'" + idFrom + "')", 'url(#' + idTo + ')')
                      newValue = newValue.replace('url(#"' + idFrom + '")', 'url(#' + idTo + ')')
                      # and now replace all the children with this new stylesheet.
                      # again, this is in case the stylesheet was a CDATASection
                      node.childNodes[:] = [node.ownerDocument.createTextNode(newValue)]
                      num += len(oldValue) - len(newValue)
  
              # if xlink:href is set to #idFrom, then change the id
              href = node.getAttributeNS(NS['XLINK'], 'href')
              if href == '#' + idFrom:
                  node.setAttributeNS(NS['XLINK'], 'href', '#' + idTo)
                  num += len(idFrom) - len(idTo)
  
              # if the style has url(#idFrom), then change the id
              styles = node.getAttribute('style')
              if styles != '':
                  newValue = styles.replace('url(#' + idFrom + ')', 'url(#' + idTo + ')')
                  newValue = newValue.replace("url('#" + idFrom + "')", 'url(#' + idTo + ')')
                  newValue = newValue.replace('url("#' + idFrom + '")', 'url(#' + idTo + ')')
                  node.setAttribute('style', newValue)
                  num += len(styles) - len(newValue)
  
              # now try the fill, stroke, filter attributes
              for attr in referencingProps:
                  oldValue = node.getAttribute(attr)
                  if oldValue != '':
                      newValue = oldValue.replace('url(#' + idFrom + ')', 'url(#' + idTo + ')')
                      newValue = newValue.replace("url('#" + idFrom + "')", 'url(#' + idTo + ')')
                      newValue = newValue.replace('url("#' + idFrom + '")', 'url(#' + idTo + ')')
                      node.setAttribute(attr, newValue)
                      num += len(oldValue) - len(newValue)
  
          del referencedIDs[idFrom]
          referencedIDs[idTo] = referringNodes
  
      return num