如何将 Base64 解码为 XML
- 把 Base64 粘贴到 输入 · Base64。页面打开时已载入一个小示例。
- XML 显示在 输出 · 文本 中。状态行中的 看起来像 XML,表示内容的开头符合 XML 文档的特征。
- 如果输出的字母之间有空隙,或者出现二进制警告,说明 XML 是 UTF-16:把 字符集 设为 UTF-16LE;如果开头有字节序标记,也可以设为 自动检测。
- 复制输出 复制文本。下载 把原始字节保存为
decoded.xml。
示例 PD94bWwgdmVyc2lvbj0iMS4wIj8+Cjxub3RlPjx0bz55b3U8L3RvPjxib2R5PkhlbGxvPC9ib2R5Pjwvbm90ZT4= 解码后为:
<?xml version="1.0"?>
<note><to>you</to><body>Hello</body></note>
反方向请使用 XML 转 Base64。
如何认出编码后的 XML
XML 以 < 开头,所以它的 Base64 以 P 开头,后面的字符还能透露更多信息:
| Base64 开头 | 解码后的开头 | 典型文档 |
|---|---|---|
PD94bWwg | <?xml | 任何带声明的 XML 文件 |
PHNhbWxwOlJlc3BvbnNl | <samlp:Response | SAML 登录响应(SAML 解码器) |
PHNvYXA6RW52ZWxvcGU | <soap:Envelope | SOAP 消息 |
PEludm9pY2U | <Invoice | UBL 电子发票 |
//48AD8AeABtAGwA | BOM + UTF-16LE 的 <?xml | 保存为 UTF-16 的 XML |
本应是 SAML 的值如果不以 P 开头,通常是压缩过的 XML;下文会说明如何解压。
UTF-16 和其他编码
大多数 XML 是 UTF-8,解码器默认也按 UTF-8 处理。有两种情况需要换一个 字符集:
- UTF-16 文档,常见于 Windows 工具和 .NET,每个 ASCII 字符旁边都有一个零字节。按 UTF-8 解码时它们看起来像二进制数据,工具也会这样提示。选择 自动检测 或 UTF-16LE 后,完整的文本就会出现,开头是
<?xml version="1.0" encoding="UTF-16"?>。下载 会保留原始字节,但文件名为decoded.bin,请把扩展名改为.xml。 - Latin-1 或 Windows-1252 文档 会声明
encoding="ISO-8859-1"之类的编码。在 UTF-8 模式下重音字母显示为�;选择声明的字符集即可正常阅读。
输出中的 XML 声明说明了作者想用的字符集。XML 解析器读取下载的文件时会依据这个声明,所以即使屏幕上的预览需要手动选择字符集,文件本身也没有问题。
Base64 XML 从哪里来
最常见的来源是 SAML:身份提供方把 SAMLResponse 以 Base64 编码的 XML 形式 POST 给你的应用,调试登录时通常从浏览器的网络面板中复制它。SOAP 服务和电子发票平台会以 Base64 字段返回文档和附件。电子邮件可以用 MIME Base64 部分携带 XML 附件,邮件解码器 可以把它们提取出来。
对于重定向 URL 中的 SAML SAMLRequest 值,XML 在编码前已用原始 DEFLATE 压缩过,所以直接做 Base64 解码得到的是二进制数据。gzip Base64 解码器 可以把它解压。转义序列 %2B、%2F 和 %3D 会被自动解码;如果整个值都经过了 URL 编码,请先使用 URL 解码器。
在代码中将 Base64 转为 XML
把解码后的字节直接交给 XML 解析器,不要先转成字符串,这样它会自己从声明中读取编码:
import base64
import xml.etree.ElementTree as ET
s = "PD94bWwgdmVyc2lvbj0iMS4wIj8+Cjxub3RlPjx0bz55b3U8L3RvPjxib2R5PkhlbGxvPC9ib2R5Pjwvbm90ZT4="
root = ET.fromstring(base64.b64decode(s))
root.find("body").text # 'Hello'
// Browser
const s = "PD94bWwgdmVyc2lvbj0iMS4wIj8+Cjxub3RlPjx0bz55b3U8L3RvPjxib2R5PkhlbGxvPC9ib2R5Pjwvbm90ZT4=";
const bytes = Uint8Array.from(atob(s), c => c.charCodeAt(0));
const doc = new DOMParser().parseFromString(new TextDecoder().decode(bytes), "application/xml");
在浏览器中处理 UTF-16 或 Latin-1 的 XML 时,请给 TextDecoder 传入正确的编码标签。详见 Python 中的 Base64 和 JavaScript 中的 Base64。
常见问题
怎么把 Base64 解码成 XML 文件?
把 Base64 粘贴到上方。状态行显示 XML 时,下载 会把解码后的字节逐字节保存为 decoded.xml,原始编码和签名都完整保留。
怎么判断 Base64 里是不是 XML?
带 XML 声明的文档以 PD94bWwg(<?xml )开头。没有声明时字符串仍以 P 开头,因为每个文档都以 < 开头;PHNhbWxwOlJlc3BvbnNl 就是 <samlp:Response。
工具能格式化或缩进 XML 吗?
不能。XML 按解码结果原样显示;“格式化 JSON”选项只对 JSON 有效。对于签名的 XML,显示原始字节很重要,任何重新格式化都会改变其内容。
为什么解码后的 SAML 请求看起来像一堆乱码字节?
通过重定向 URL 发送的 SAML 请求在 Base64 编码之前先用原始 DEFLATE 压缩过。请用 gzip Base64 解码器 解压,或者在 SAML 解码器 中打开。