XML文件如何转换为Markdown 表格数据转MD格式的脚本

2次阅读

xml.etree.elementtree适合解析结构清晰的xml,需注意编码、空值处理、字段映射及markdown转义;避免模糊xpath,统一用(text or ”).strip()取值,表头与分隔行需规范生成。

XML文件如何转换为Markdown 表格数据转MD格式的脚本

XML 解析用 xml.etree.ElementTree 最轻量

Python 自带的 xml.etree.ElementTree 足够应付绝大多数结构清晰的 XML 表格数据(比如配置导出、简单报表),不用装第三方库。它不支持 DTD 或命名空间复杂的 XML,但如果你的 XML 是类似 <row><col1>A</col1><col2>B</col2></row> 这种扁平结构,直接上手就行。

常见错误现象:ParseError: not well-formed (invalid Token) —— 多半是 XML 里混了未转义的 &、<code>>,或编码不是 UTF-8(尤其 windows 记事本保存的 XML 常带 bom)。先用文本编辑器确认编码,再用 open(... , encoding='utf-8') 显式指定。

  • 优先用 ET.parse() 加载文件;若内容来自字符串,用 ET.fromstring()
  • 避免用 findall('.//row') 这种模糊路径——性能差,且容易漏掉嵌套层级变化的 case
  • 列名建议从首行 <row></row> 的子节点 tag 推断,别硬编码 ['name', 'age', 'city'],否则 XML 字段一变脚本就挂

提取字段时别直接取 .text,要处理空值和换行

XML 里的 <age></age><city></city>,用 elem.text 会得到 None;而 <note> hello </note> 会带前后空白和换行。Markdown 表格里塞 None 或缩进空格,渲染出来就是错位或空格乱码。

使用场景:你拿到的 XML 可能由不同系统导出,有的字段留空用自闭合标签,有的用空标签,有的干脆缺失节点。

  • 统一用 (elem.text or '').strip() 获取内容
  • 如果某列必须有值,但 XML 中可能缺失,用 elem.find('col_name') or elem.find('.//col_name') 再判空,别假设层级固定
  • 表格中禁止出现 |^ 等 Markdown 表格分隔符,提前用 .replace('|', '|').replace(' ', ' ') 简单转义

生成 Markdown 表格头和分隔行有固定写法

Markdown 表格不是靠缩进或空格对齐,而是靠 | 分隔 + 第二行用 |---|---| 定义对齐方式。很多人手写时漏掉第二行,或在分隔行里混用 : 导致解析失败。

性能影响:表头和分隔行只需生成一次,不要在循环里重复拼接;字段名数量大时(比如 50+ 列),用 ['|'] + [f' {h} ' for h in headers] + ['|'] 比字符串 + 拼接快。

  • 表头行:拼成 | col1 | col2 | col3 |
  • 分隔行:对应列统一用 |---|---|---|(左对齐);需要右对齐某列?写成 |---:|;居中?|:-:|
  • 每行数据也必须以 | 开头和结尾,中间每个字段用 | 隔开,字段内不能有未转义的 |

中文字段名或含空格的 tag 名需映射为合法列名

XML 里常有 <order date></order> 这类 tag,直接当表头会导致 Markdown 渲染异常(空格破坏分隔逻辑,中文本身没问题但可读性差),更麻烦的是后续想用 pandas 处理时字段名不合法。

容易踩的坑:有人用正则删所有非字母数字,结果 user_iduserid 全变成 userid,冲突了。

  • 建议做最小映射:空格 → _,中文 → 直接保留(Markdown 表格支持),特殊符号如 @._
  • 加个去重逻辑:如果两个 tag 映射后相同(如 <user id></user><user_id></user_id> 都变 user_id),在后面追加序号 user_id_1user_id_2
  • 这个映射最好单独抽成函数,调试时打印原始 tag → 映射名对照表,比盲猜靠谱

真正麻烦的不是解析 XML,是 XML 结构不一致——同一份 XSD 下,某次导出多了一层 <data><rows><row></row></rows></data>,下次又扁平成 <row></row>。别指望一个脚本永远通用,每次换数据源前,先 print(ET.tostring(root, encoding='unicode')[:200]) 看一眼顶层结构。

text=ZqhQzanResources