def generate_changeset(old, new, comment=None):
rrsets_tag = '<STR_LIT>' % R53_XMLNS<EOL>if rrsets_tag not in (old.tag, new.tag):<EOL><INDENT>log.error('<STR_LIT>' % (old.tag, new.tag))<EOL>raise InvalidArgumentException()<EOL><DEDENT>if comment is None:<EOL><INDENT>comment = '<STR_LIT>' % (<EOL>__file__,<EOL>os.environ['<STR_LIT>'],<EOL>socket.gethostname(),<EOL>time.strftime('<STR_LIT>'))<EOL><DEDENT>root = lxml.etree.XML("""<STR_LIT>""" % (<EOL>R53_XMLNS, comment), parser=XML_PARSER)<EOL>changesroot = root.find('<STR_LIT>' % R53_XMLNS)<EOL>old = normalize_rrs(old)<EOL>new = normalize_rrs(new)<EOL>oldset = set([lxml.etree.tostring(x).rstrip() for x in old])<EOL>newset = set([lxml.etree.tostring(x).rstrip() for x in new])<EOL>if oldset == newset:<EOL><INDENT>return None<EOL><DEDENT>for rrs in old:<EOL><INDENT>rrsst = lxml.etree.tostring(rrs).rstrip()<EOL>if rrsst not in newset:<EOL><INDENT>log.debug("<STR_LIT>")<EOL>log.debug(rrsst)<EOL>change = lxml.etree.XML('<STR_LIT>' % R53_XMLNS, parser=XML_PARSER)<EOL>change.append(rrs)<EOL>changesroot.append(change)<EOL><DEDENT><DEDENT>for rrs in new:<EOL><INDENT>rrsst = lxml.etree.tostring(rrs).rstrip()<EOL>if rrsst not in oldset:<EOL><INDENT>log.debug("<STR_LIT>")<EOL>log.debug(rrsst)<EOL>change = lxml.etree.XML('<STR_LIT>' % R53_XMLNS, parser=XML_PARSER)<EOL>change.append(rrs)<EOL>changesroot.append(change)<EOL><DEDENT><DEDENT>return root<EOL>
Diff two XML configs and return an object with changes to be written.

    Args: old, new: lxml.etree.Element (<ResourceRecordSets>).
    Returns: lxml.etree.ETree (<ChangeResourceRecordSetsRequest>) or None