swift报文解析必须严格按{1:}{2:}{3:}{4:}四块拆分并依mt类型规范映射:{1:}{2:}转header扁平字段,{3:}保留安全域,{4:}用正则提取标签并处理续行与复合结构,生成xml需绑定官方xsd校验。

SWIFT 报文(如 MT103、MT202COV)是纯文本格式,结构严格但无嵌套语义,直接转 XML 不能靠简单换行或正则硬切——必须按 SWIFT 标准解析字段边界({1:}、{2:}、{3:}、{4:} 等块),再按 MT 类型的官方规范映射字段层级。
识别并拆分 SWIFT 报文的四个逻辑块
SWIFT 报文由 {1:}(会话头)、{2:}(应用头)、{3:}(用户头)、{4:}(正文)四部分组成,每部分以 {n:} 开头、{n:} 或 -} 结尾。漏掉任一块,XML 就会丢失路由、优先级或业务数据。
-
{1:}和{2:}是纯控制信息(如发送方BIC、时间戳),适合转为 XML 的<header></header>下扁平字段 -
{3:}含可选安全域,金融合规场景下必须保留,不能跳过 -
{4:}是核心业务块,以冒号分隔的标签字段(如:20:、:32A:)构成,必须按 MT 类型定义逐字段解析——:32A:在 MT103 中是起息日+币种+金额,在 MT700 中则完全不存在
用 Python 解析 {4:} 块时避开常见字段截断错误
SWIFT 字段值允许换行(用 + 行首续行),且字段间可能有空行或注释行(以 -} 结尾)。直接 split(':') 或按行切分必然错乱。
- 必须先用正则
re.split(r'(:\w+?:)', text)提取带冒号的完整标签(如:20:、:59:),再配对后续非标签内容 - 遇到
:20C:这类复合标签(含子类型),需额外判断下一行是否为/开头的引用标识(如/ACC/123456789) - 字段值中的冒号(如
:70:交易附言里的英文冒号)不构成新字段,必须依赖标签边界而非字符串冒号
import re
<p>def parse_mt_block(block):</p><h1>提取所有 :XX: 或 :XXY: 形式标签(支持字母+数字+可选字母后缀)</h1><pre class='brush:php;toolbar:false;'>tags = re.findall(r':[A-Z0-9]{2,3}:', block)
parts = re.split(r'(:[A-Z0-9]{2,3}:)', block)
result = {}
for i in range(1, len(parts), 2):
if i + 1 < len(parts) and parts[i].startswith(':'):
tag = parts[i]
value = parts[i + 1].strip()
# 清除续行符 '+' 和前导空格,但保留内部换行(如 :70: 内容)
value = re.sub(r'\n\s*\+', ' ', value)
result[tag] = value
return result生成合规 XML 时必须绑定 MT 类型 Schema
不同 MT 类型字段语义不同,同一标签在不同报文中含义可能冲突(如 :57A: 在 MT103 是收款行,在 MT202 是代理行)。硬编码 XML 结构会导致反向解析失败或监管审计不通过。
- 不要手写
<mt103><sender>...</sender></mt103>,应加载 ISO 20022 或 SWIFT 官方 XSD(如mt103.002.001.08.xsd)做运行时校验 - 字段缺失处理要区分:必填字段(如
:20:)为空时报错;可选字段(如:77B:)为空时 XML 中省略节点,而非填空字符串 - 金额字段(
:32A:)必须拆成<currency>USD</currency><amount>1000,00</amount>,不能合并为一个文本节点
真正难的不是转换动作本身,而是当客户发来一份「自称 MT103」但实际混用了 MT202 字段的报文时,你的解析器能否识别异常、定位到具体哪一行违反了 MT103_2018.pdf 第 4.2.3 节规则,并给出可操作的修复建议——这需要把 SWIFT 用户手册当字典查,而不是只盯着代码逻辑。










