如何用Python对比draw.io SOP流程图XML并生成差异图像?
需求可行性及Python实现方案
这个需求完全可行。draw.io(现称Diagrams.net)的文件本质是XML结构,每个图形元素(形状、连接线、分组等)都对应XML中的<mxCell>节点,包含样式、位置、内容等属性。通过解析对比前后版本的XML,定位差异元素后,可通过修改XML样式或图像后处理生成高亮对比图。
核心实现步骤
解析draw.io XML文件
draw.io的XML结构中,工作表(<mxGraphModel>下的<root>)包含所有图形元素。用Python的xml.etree.ElementTree或lxml库读取文件,提取每个<mxCell>的关键属性(ID、样式、几何坐标、文本内容、父节点/连接关系等),存入字典方便对比。对比XML元素差异
- 按元素ID匹配,快速找出新增(新XML有、旧XML无)、删除(旧XML有、新XML无)的元素。
- 对ID匹配的元素,逐一对比属性:样式(
style)、文本(value)、几何坐标(<mxGeometry>的x/y/width/height)、连接关系(source/target),标记修改的元素。 - 针对复杂流程图的分组元素,需递归检查父节点变化对子元素的影响(比如分组样式修改时,子元素也需标记)。
生成差异高亮图像
有两种主流实现方式:- XML修改导出法:修改新版本的XML,给差异元素添加高亮样式(比如半透明蓝色填充
fillColor=#0000ff80),再用draw.io的命令行工具导出为带高亮的PNG。这种方式精准度高,适合复杂图形。 - 图像后处理法:先将前后版本的XML分别导出为PNG,再用
Pillow库根据差异元素的几何坐标,在图像上绘制高亮框或叠加半透明色块。适合快速生成对比图。
- XML修改导出法:修改新版本的XML,给差异元素添加高亮样式(比如半透明蓝色填充
简化代码示例
1. 解析与对比XML
import xml.etree.ElementTree as ET def parse_drawio_cells(file_path): """解析draw.io XML,返回元素ID到属性的字典""" tree = ET.parse(file_path) root = tree.getroot() cell_dict = {} for cell in root.findall('.//mxCell'): cell_id = cell.get('id') geo = cell.find('mxGeometry') cell_dict[cell_id] = { 'style': cell.get('style', ''), 'value': cell.get('value', ''), 'geometry': geo.attrib if geo is not None else {}, 'parent': cell.get('parent'), 'source': cell.get('source'), 'target': cell.get('target') } return cell_dict def find_cell_diffs(old_cells, new_cells): """对比两个元素字典,返回新增、删除、修改的元素ID""" added = [cid for cid in new_cells if cid not in old_cells] removed = [cid for cid in old_cells if cid not in new_cells] modified = [] for cid in old_cells: if cid not in new_cells: continue old_attr = old_cells[cid] new_attr = new_cells[cid] # 对比关键属性 if (old_attr['style'] != new_attr['style'] or old_attr['value'] != new_attr['value'] or old_attr['geometry'] != new_attr['geometry'] or old_attr['source'] != new_attr['source'] or old_attr['target'] != new_attr['target']): modified.append(cid) return added, removed, modified
2. 给差异元素添加高亮样式
def apply_highlight_to_xml(input_xml, output_xml, highlight_ids): """给指定ID的元素添加半透明蓝色高亮""" tree = ET.parse(input_xml) root = tree.getroot() for cell in root.findall('.//mxCell'): if cell.get('id') in highlight_ids: current_style = cell.get('style', '') # 避免重复添加样式 if 'fillColor=#0000ff80' not in current_style: cell.set('style', f"{current_style};fillColor=#0000ff80;") tree.write(output_xml, encoding='utf-8', xml_declaration=True)
3. 用drawio命令行导出图像
确保已安装drawio桌面版,执行以下命令导出高亮后的XML为PNG:
drawio -x -f png -o highlighted_sop.png modified_highlighted.xml
复杂流程图注意事项
- 处理嵌套分组:当父分组元素被修改时,需递归标记所有子元素。
- 连接线差异:重点对比
source和target属性,判断连接关系是否变化。 - 样式合并:修改样式时需保留原有样式(比如边框、字体),仅追加高亮属性。
内容的提问来源于stack exchange,提问作者Carlos Alberto
相关产品推荐
相关产品推荐

