如何将draw.io导出PNG文件中的压缩数据转换为XML格式
解决方法
你当前从tEXt块提取到的第二个元素是经过URL编码的mxfile结构,其中<diagram>标签包裹的内容是经过Base64编码+Deflate压缩的绘图数据,按以下步骤解码即可得到完整XML:
import png import urllib.parse import base64 import zlib from xml.etree import ElementTree as ET filename = "./image3.png" # 读取PNG所有块 reader = png.Reader(filename) chunks = list(reader.chunks()) # 定位tEXt块中key为mxfile的内容 mxfile_encoded = None for chunk_type, chunk_data in chunks: if chunk_type == b"tEXt": parts = chunk_data.split(b"\x00", 1) if parts[0] == b"mxfile": mxfile_encoded = parts[1].decode("utf-8") break if not mxfile_encoded: raise ValueError("PNG中未找到draw.io存储的mxfile数据") # 第一步:URL解码得到外层mxfile结构 outer_mxfile_str = urllib.parse.unquote(mxfile_encoded) outer_root = ET.fromstring(outer_mxfile_str) diagram_elem = outer_root.find("diagram") compressed_b64 = diagram_elem.text.strip() # 第二步:Base64解码+zlib解压得到内部mxGraphModel结构 compressed_data = base64.b64decode(compressed_b64) # wbits=-15 代表使用Raw Deflate格式,适配draw.io的压缩规则 xml_inner = zlib.decompress(compressed_data, wbits=-15).decode("utf-8") # 组装完整XML full_xml = f"""<?xml version="1.0" encoding="UTF-8"?> {ET.tostring(outer_root, encoding="unicode").split("><diagram")[0]}> <diagram id="{diagram_elem.get('id')}" name="{diagram_elem.get('name')}"> {xml_inner} </diagram> </mxfile> """ print(full_xml)
代码说明
- 兼容tEXt/zTXt两种块格式,无论draw.io导出时选择压缩还是非压缩存储,都能正常读取
- 最终输出的XML结构可直接导入draw.io编辑使用
内容的提问来源于stack exchange,提问作者Igor L.
相关产品推荐
相关产品推荐

