¿Cómo incrustar datos binarios en XML?


Tengo dos aplicaciones escritas en Java que se comunican entre sí usando mensajes XML a través de la red. Estoy usando un analizador de 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 cómo hacer esto?

ACTUALIZACIÓN: Tengo esto trabajando con la clase Base64 de la biblioteca de códecs apache commons, en caso de que alguien más esté intentando algo similar.

Author: Peter17, 2008-08-21

13 answers

Puede codificar los datos binarios usando base64 y colocarlos en un elemento Base64; el siguiente artículo es bastante bueno sobre el tema.

Manejo de Datos Binarios en Documentos XML

 196
Author: Greg Hurlman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-11 14:08:11

XML es muy 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:

POR cierto: Base64 + CDATA es probablemente la mejor solución

(EDIT2:
Quienquiera que me ayude, por favor también mejore la respuesta real. No queremos que ninguna pobre alma venga aquí e implemente mi método porque fue el mejor clasificado, ¿verdad?)

 192
Author: Mo.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-21 14:18:17

Base64 es de hecho la respuesta correcta, pero CDATA no lo es, eso es básicamente diciendo: "esto podría ser cualquier cosa", sin embargo debe no ser cualquier cosa, tiene que ser Base64 codificado datos binarios. El esquema XML define Binario Base 64 como un tipo de datos primitivo que puede usar en su xsd.

 22
Author: Boris Terzic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-21 17:44:17

Tuve este problema la semana pasada. Tuve que serializar un archivo PDF y enviarlo, dentro de un archivo XML, a un servidor.

Si está utilizando.NET, puede convertir un archivo binario directamente a una cadena base64 y pegarlo dentro de un elemento XML.

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

O bien, hay un método integrado directamente 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 se ve 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>
 9
Author: Baxter Tidwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-03 21:35:11

Normalmente codifico los datos binarios con MIME Base64 o URL encoding.

 6
Author: Anders Sandvig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-21 13:38:36

Pruebe Base64 codificando/decodificando sus datos binarios. También vea las secciones de CDATA

 5
Author: basszero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-21 13:37:52

Tal vez codificarlos en un conjunto conocido - algo como base 64 es una opción popular.

 4
Author: mercutio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-21 13:37:19

Cualquier codificación binaria a texto hará el truco. Yo uso algo así

<data encoding="yEnc>
<![CDATA[ encoded binary data ]]>
</data>
 4
Author: Jarek Przygódzki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-01 08:31:40

La sobrecarga de Base64 es del 33%.

BaseXML para XML1.0 la sobrecarga es solo del 20%. Pero no es un estándar y solo tiene una implementación de C todavía. Échale un vistazo si te preocupa el tamaño de los datos. Tenga en cuenta que, sin embargo, los navegadores tienden a implementar la compresión para que sea menos necesaria.

Lo desarrollé después de la discusión en este hilo: Codificar datos binarios dentro de XML : alternativas a base64.

 3
Author: KrisWebDev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:59

También puedes codificar tus datos binarios originales. Este formato es un poco más antiguo, pero hace lo mismo que la codificación base63.

 2
Author: Andrei Savu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-31 16:52:05

No utilice la codificación base64, ya que aumenta la cantidad de datos que necesita almacenar en al menos un 40%. En lugar de utilizar otros métodos de codificación como yEnc.

 2
Author: Jamie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-17 10:01:12

Este es un buen ejemplo de cómo proceder XEP-0239

PD: no te olvides de leer la respuesta de Mo.

PS2: lea la sección de AVISOS en el XEP.

 0
Author: mschonaker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:33:25

Si usted tiene control sobre el formato XML, usted debe dar vuelta al problema de adentro hacia afuera. En lugar de adjuntar el XML binario, debería pensar en cómo adjuntar un documento que tiene varias partes, una de las cuales contiene XML.

La solución tradicional para esto es un archivo (por ejemplo, tar). Pero si desea mantener su documento adjunto en un formato basado en texto o si no tiene acceso a una biblioteca de archivado de archivos, también hay un esquema estandarizado que se utiliza en gran medida en el correo electrónico y HTTP que es multipart/* MIME con Content-Transfer-Encoding: binary.

Por ejemplo, si sus servidores se comunican a través de HTTP y desea enviar un documento multiparte, el principal es un documento XML que se refiere 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 que encierra mediante un esquema URI cid que es un identificador para el encabezado Content-Id. El la sobrecarga de este esquema sería solo la cabecera MIME. Un esquema similar también se puede utilizar 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 separada.

Si desea evitar envolver sus datos en una multiparte es usar URI de datos:

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

Pero esto tiene la sobrecarga base64.

 0
Author: Lie Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-10 08:42:35