java - ¿Cómo incrusta datos binarios en XML?
binary binary-data (13)
Tengo dos aplicaciones escritas en Java que se comunican entre sí utilizando mensajes XML a través de la red. Estoy usando un analizador SAX en el extremo receptor para recuperar los datos de los mensajes. Uno de los requisitos es incrustar datos binarios en un mensaje XML, pero a SAX no le gusta esto. ¿Alguien sabe como hacer esto?
ACTUALIZACIÓN: Obtuve esto trabajando con la clase Base64 de la biblioteca de códec de Apache commons , en caso de que alguien más esté intentando algo similar.
Aquí hay un buen ejemplo de cómo proceder XEP-0239
PD: no olvides leer la respuesta de Mo.
PS2: lea la sección NOTICE en el XEP.
Base64 es sin duda la respuesta correcta, pero CDATA no lo es, básicamente dice: "esto podría ser cualquier cosa", sin embargo, no debe ser nada, tiene que ser datos binarios codificados en Base64. El Esquema XML define el binario de Base 64 como un tipo de datos primitivo que puede usar en su xsd.
Cualquier codificación de binario a texto hará el truco. Yo uso algo así
<data encoding="yEnc>
<![CDATA[ encoded binary data ]]>
</data>
La sobrecarga de Base64 es del 33%.
BaseXML de BaseXML para XML1.0 es solo del 20% . Pero no es un estándar y solo tiene una implementación C todavía. Compruébelo si le preocupa el tamaño de los datos. Sin embargo, tenga en cuenta que los navegadores tienden a implementar la compresión para que sea menos necesaria.
Lo desarrollé después de la discusión en este hilo: Codificación de datos binarios dentro de XML: alternativas a base64 .
No use la codificación base64 ya que aumenta la cantidad de datos que necesita almacenar al menos un 40%. Más bien use otros métodos de codificación como yEnc.
Normalmente codifico los datos binarios con MIME Base64 o codificación URL .
Podrías codificar los datos binarios usando base64 y ponerlos en un elemento Base64; el siguiente artículo es bastante bueno sobre el tema.
Pruebe la codificación / decodificación de Base64 de sus datos binarios. También busque en las secciones de CDATA
Quizás codificarlos en un conjunto conocido: algo así como base 64 es una opción popular.
Si tiene control sobre el formato XML, debe volver el problema al revés. En lugar de adjuntar el XML binario, debe pensar en cómo adjuntar un documento que tiene varias partes, una de las cuales contiene XML.
La solución tradicional a esto es un archivo (por ejemplo, alquitrán). Pero si desea conservar su documento adjunto en un formato de texto o si no tiene acceso a una biblioteca de archivado de archivos, también hay un esquema estandarizado que se usa mucho en correo electrónico y HTTP que es multipart / * MIME con Content-Transfer-Encoding: binario .
Por ejemplo, si sus servidores se comunican a través de HTTP y desea enviar un documento de varias partes, siendo el principal un documento XML que hace referencia a datos binarios, la comunicación HTTP podría tener un aspecto similar a este:
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--
Como en el ejemplo anterior, el XML se refiere a los datos binarios en la multiparte adjunta utilizando un esquema de URI cid
que es un identificador del encabezado Content-Id. La sobrecarga de este esquema sería solo el encabezado MIME. Un esquema similar también se puede usar para la respuesta HTTP. Por supuesto, en el protocolo HTTP, también tiene la opción de enviar un documento de varias partes en una solicitud / respuesta por separado.
Si quiere evitar envolver sus datos en una multiparte es usar el URI de datos:
<myxml>
<data href="data:application/something;charset=utf-8;base64,dGVzdGRhdGE="/>
</myxml>
Pero esto tiene la base64 de arriba.
También puede Uuencode sus datos binarios originales. Este formato es un poco más antiguo pero hace lo mismo que la codificación base63.
Tuve este problema la semana pasada. Tuve que serializar un archivo PDF y enviarlo, dentro de un archivo XML, a un servidor.
Si usa .NET, puede convertir un archivo binario directamente en una cadena base64 y pegarlo dentro de un elemento XML.
string base64 = Convert.ToBase64String(File.ReadAllBytes(fileName));
O bien, hay un método integrado en el objeto XmlWriter. En mi caso particular, tuve que incluir el espacio de nombres de tipo de datos de 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();
La cadena abc parece algo así:
<?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>
XML es tan versátil ...
<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 es como violencia: si no resuelve tu problema, no estás usando suficiente.
EDITAR:
BTW: Base64 + CDATA es probablemente la mejor solución
(EDIT2:
Quien me modifique, por favor también modifique la respuesta real. No queremos que ningún alma pobre venga aquí y realmente implemente mi método porque fue el mejor clasificado en SO, ¿no?)