如何在XML中embedded二进制数据?

我有两个用Java编写的应用程序,它们使用networking上的XML消息相互通信。 我在接收端使用一个SAXparsing器将数据从消息中取出。 其中一个要求是将二进制数据embedded到XML消息中,但是SAX不喜欢这样做。 有谁知道如何做到这一点?

更新:我得到了这个从apache commons编解码库的Base64类,以防其他人正在尝试类似的东西。

你可以使用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可能是最好的解决scheme

(EDIT2:
无论谁调高我,也请提出真正的答案。 我们不希望任何可怜的灵魂来这里,实际上实施我的方法,因为它是最高的排名,对吧?)

Base64确实是正确的答案,但是CDATA不是,那基本上是这样说的:“这可能是任何东西”,但它绝不能只是任何东西,它必须是Base64编码的二进制数据。 XML Schema将Base 64二进制文件定义为可在xsd中使用的基本数据types 。

我上周刚刚遇到这个问题。 我不得不序列化一个PDF文件,并将其发送到一个XML文件中,到一个服务器。

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

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

或者,在XmlWriter对象中内置一个方法。 在我的情况下,我不得不包括微软的数据types命名空间:

 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(); 

stringabc看起来像这样:

 <?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部分

也许把它们编码成一个已知的集合 – 像64位是一个stream行的select。

任何二进制到文本编码都可以做到这一点。 我使用这样的东西

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

Base64开销是33%。

BaseXML for XML1.0的开销只有20% 。 但这不是一个标准,只有C实现。 如果您关心数据大小,请检查一下。 请注意,不过浏览器倾向于实现压缩,因此不太需要。

我在这个线程的讨论之后开发了它: 编码XML中的二进制数据:base64的替代品 。

你也可以Uuencode你原来的二进制数据。 这种格式有点旧了,但是和base63编码一样。

不要使用base64编码,因为它会将您需要存储的数据量增加至less40%。 而是使用其他编码方法,如yEnc。

这是一个如何进行XEP-0239的好例子

PS:不要忘记读Mo的回答 。

PS2:阅读XEP上的NOTICE部分。

如果您能够控制XML格式,则应该将问题从内部转移出去。 而不是附加二进制XML,您应该考虑如何附加包含多个部分的文档,其中之一包含XML。

传统的解决scheme是档案(例如焦油)。 但是,如果你想保留你的封闭文件为基于文本的格式,或者如果你没有访问文件归档库,还有一个标准化的scheme,在电子邮件和HTTP是multipart / * MIME Content-Transfer-Encoding:二进制 。

例如,如果您的服务器通过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通过使用作为Content-Id标题的标识符的cid URIscheme来引用封闭多部分中的二进制数据。 这个scheme的开销只是MIME头。 HTTP响应也可以使用类似的scheme。 当然,在HTTP协议中,您也可以select将多部分文档发送到单独的请求/响应中。

如果你想避免在多部分包装你的数据是使用数据的URI:

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

但是这有base64的开销。