我有两个用 Java 编写的应用程序,它们通过网络使用 XML 消息相互通信。我在接收端使用 SAX 解析器从消息中获取数据。要求之一是将二进制数据嵌入 XML 消息中,但 SAX 不喜欢这样。有谁知道如何做到这一点?

更新:我得到了这个与 Base64 类来自 Apache Commons 编解码器库, ,以防其他人正在尝试类似的事情。

有帮助吗?

解决方案

您可以使用 Base64 对二进制数据进行编码并将其放入 Base64 元素中;下面的文章是关于这个主题的一篇非常好的文章。

处理 XML 文档中的二进制数据

其他提示

XML 是如此多才多艺......

<DATA>
  <BINARY>
    <BIT index="0">0</BIT>
    <BIT index="1">0</BIT>
    <BIT index="2">1</BIT>
    ...
    <BIT index="n">1</BIT>
  </BINARY>
</DATA>

XML 就像暴力——如果它不能解决您的问题,那么您就没有使用足够的它。

编辑:

顺便提一句:Base64 + CDATA 可能是最好的解决方案

(编辑2:
谁upmod了我,也请upmod真正的答案。我们不希望任何可怜的灵魂来到这里并实际实施我的方法,因为它是 SO 上排名最高的,对吗?)

Base64 确实是正确的答案,但 CDATA 不是,这基本上是说:“这可以是任何东西”,但是它必须 不是 可以是任何东西,它必须是 Base64 编码的二进制数据。XML 模式定义 Base 64 二进制作为原始数据类型 您可以在 xsd 中使用它。

我上周就遇到了这个问题。我必须序列化 PDF 文件并将其以 XML 文件形式发送到服务器。

如果您使用 .NET,则可以将二进制文件直接转换为 Base64 字符串并将其粘贴到 XML 元素内。

string base64 = Convert.ToBase64String(File.ReadAllBytes(fileName));

或者,XmlWriter 对象中内置了一个方法。在我的特定情况下,我必须包含 Microsoft 的数据类型命名空间:

StringBuilder sb = new StringBuilder();
System.Xml.XmlWriter xw = XmlWriter.Create(sb);
xw.WriteStartElement("doc");
xw.WriteStartElement("serialized_binary");
xw.WriteAttributeString("types", "dt", "urn:schemas-microsoft-com:datatypes", "bin.base64");
byte[] b = File.ReadAllBytes(fileName);
xw.WriteBase64(b, 0, b.Length);
xw.WriteEndElement();
xw.WriteEndElement();
string abc = sb.ToString();

字符串 abc 看起来像这样:

<?xml version="1.0" encoding="utf-16"?>
<doc>
    <serialized_binary types:dt="bin.base64" xmlns:types="urn:schemas-microsoft-com:datatypes">
        JVBERi0xLjMKJaqrrK0KNCAwIG9iago8PCAvVHlwZSAvSW5mbw...(plus lots more)
    </serialized_binary>
</doc>

我通常用以下方式对二进制数据进行编码 MIME Base64 或者 URL编码.

尝试 Base64 编码/解码您的二进制数据。另请参阅 CDATA 部分

也许将它们编码成一个已知的集合 - 像 Base 64 这样的东西是一个流行的选择。

任何 二进制到文本编码 会成功的。我用类似的东西

<data encoding="yEnc>
<![CDATA[ encoded binary data ]]>
</data>

虽然其他答案大多都很好,但您可以尝试另一种更节省空间的编码方法,例如 yEnc。(yEnc 维基百科链接) 使用 yEnc 还可以“开箱即用”获得校验和功能。阅读下面的链接。当然,由于 XML 没有本机 yEnc 类型,因此您的 XML 模式应该更新以正确描述编码节点。

为什么: :由于编码策略base64/63、uuencode等。编码使您需要存储和传输的数据量(开销)增加大约 40%(相对于yEnc 的 1-2%)。根据您编码的内容,40% 的开销可能会成为一个问题。


yEnc - 维基百科摘要: https://en.wikipedia.org/wiki/YEncyEnc 是一种二进制到文本的编码方案,用于在 Usenet 上或通过电子邮件传输消息中的二进制文件。...与以前的编码方法(例如 uuencode 和 Base64)相比,yEnc 的另一个优点是包含 CRC 校验和来验证解码的文件是否已完整交付。‎

Base64 开销为 33%。

基础XML 用于XML1.0 开销仅为20%. 。但它不是一个标准,并且只有 C 实现。如果您关心数据大小,请检查一下。请注意,但是浏览器倾向于实现压缩,因此不太需要它。

我在这个线程的讨论之后开发了它: 在 XML 中编码二进制数据:Base64 的替代方案.

你也可以 Uu编码 你原来的二进制数据。这种格式有点旧,但它与 Base63 编码的作用相同。

如果您可以控制 XML 格式,则应该彻底解决问题。您应该考虑如何封装包含多个部分(其中之一包含 XML)的文档,而不是附加二进制 XML。

传统的解决方案是存档(例如柏油)。但是,如果您想以基于文本的格式保存随附文档,或者您无法访问文件归档库,则还有一种在电子邮件和 HTTP 中大量使用的标准化方案,即 多部分/* MIME内容传输编码:二进制.

例如,如果您的服务器通过 HTTP 进行通信,并且您想要发送多部分文档(主要是引用二进制数据的 XML 文档),则 HTTP 通信可能如下所示:

POST / HTTP/1.1
Content-Type: multipart/related; boundary="qd43hdi34udh34id344"
... other headers elided ...

--qd43hdi34udh34id344
Content-Type: application/xml

<myxml>
    <data href="cid:data.bin"/>
</myxml>
--qd43hdi34udh34id344
Content-Id: <data.bin>
Content-type: application/octet-stream
Content-Transfer-Encoding: binary

... binary data ...
--qd43hdi34udh34id344--

如上面的示例所示,XML 通过使用 cid URI 方案是 Content-Id 标头的标识符。该方案的开销只是 MIME 标头。类似的方案也可以用于 HTTP 响应。当然,在 HTTP 协议中,您还可以选择将多部分文档发送到单独的请求/响应中。

如果您想避免将数据包装在多部分中,请使用数据 URI:

<myxml>
    <data href="data:application/something;charset=utf-8;base64,dGVzdGRhdGE="/>
</myxml>

但这有 Base64 开销。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top