from xml.sax.saxutils import escape, quoteattr from emit import Emit from param import known_param_fields, known_units from lxml import etree # Emit ArduPilot documentation in an machine readable XML format for Mission Planner class XmlEmitMP(Emit): def __init__(self, *args, **kwargs): Emit.__init__(self, *args, **kwargs) self.mp_fname = 'ParameterMetaData.xml' self.f = open(self.mp_fname, mode='w') self.preamble = '''<?xml version="1.0" encoding="utf-8"?>\n''' self.f.write(self.preamble) self.f.write('<Params>\n') self.gname = None self.skip_name = False def close(self): self.f.write(' </%s>\n' % self.gname) self.f.write('''</Params>\n''') self.f.close() # sort and reformat XML parser = etree.XMLParser(remove_blank_text=True) tree = etree.parse(self.mp_fname, parser) root = tree.getroot() vehicle = tree.find(self.gname) sort_xml_node(vehicle) sorted_unicode = etree.tostring(root, pretty_print=True, encoding='unicode') f = open(self.mp_fname, mode='w') f.write(self.preamble) f.write(sorted_unicode) f.close() def emit_comment(self, s): self.f.write("<!-- " + s + " -->") def start_libraries(self): self.skip_name = True def emit(self, g): t = "" if not self.skip_name: self.gname = g.reference if self.gname == "ArduCopter": self.gname = "ArduCopter2" if self.gname == "APMrover2" or self.gname == "Rover": self.gname = "ArduRover" t = ' <%s>\n' % self.gname for param in g.params: # Begin our parameter node # Get param name and and remove key name = param.name.split(':')[-1] t += ' <%s>\n' % name if hasattr(param, 'DisplayName'): t += ' <DisplayName>%s</DisplayName>\n' % param.DisplayName if hasattr(param, 'Description'): t += ' <Description>%s</Description>\n' % escape(param.Description) # i.e. parameter docs if hasattr(param, 'User'): t += ' <User>%s</User>\n' % param.User # i.e. Standard or Advanced # not used yet # if hasattr(param, 'Calibration'): # t += ' <Calibration>%s</Calibration\n' % quoteattr(param.Calibration) # Add values as chidren of this node for field in param.__dict__.keys(): if field not in ['name', 'DisplayName', 'Description', 'User'] and field in known_param_fields: t += ' <%s>%s</%s>\n' % (field, escape(param.__dict__[field]), field) t += ' </%s>\n' % name # print t self.f.write(t) def sort_xml_node(node): if not isinstance(node.tag, str): # not a TAG, it is comment or DATA # no need to sort return # sort child along attr node[:] = sorted(node, key=lambda field: field.tag) # and recurse for child in node: child[:] = sorted(child, key=lambda field: field.tag)